I want to mock a object method that is called many times, and each times the result must be different.
Here what I'm trying to do:
fooMock.demand.someMethod(3..3) { ->
//call1
if (**some condition**)
return 1
//call2
if (**some condition**)
return 2
//call3
if (**some condition**)
return 3
}
So, is there a way to know what is the current call number ? or do you offers something better ?
It will be possible to do that in Grails 2.3-M2 (http://jira.grails.org/browse/GRAILS-4611) but until then, did someone has a workaround ?
You can create an attribute in your test to control that:
class MyTest {
int someMethodCount
#Before
void setup() {
fooMock.demand.someMethod(3..3) { ->
someMethodCount++
...
}
}
}
If you do not care about strict mocking and are only unit testing someMethod then you can use the primitive methodology of using maps:
void testSomething() {
def mockUtil = ["someMethod" : {param->
//I have used param only to handle conditional logics
//param can be optional
if(param == 1)return "John"
if(param == 2)return "Nancy"
if(param == 3)return "Mark"
}]
assert mockUtil.someMethod(1) == "John"
assert mockUtil.someMethod(2) == "Nancy"
assert mockUtil.someMethod(3) == "Mark"
}
Related
void main() => Foo() == 1;
class Foo {
#override
bool operator ==(Object other) {
print(super == this); // true
// print(this == super); // Compile error
return super == other;
}
}
There are 2 questions.
Why can't I do this == super?
If you look at the return statement return super == other, you can tell the operator == is called on the Object class, so is the entire == implementation not a call which has been delegated to the Object class?
Let me explain the 2nd question further if it wasn't clear. Let's say I check for
Foo() == 1
The == operator defined in Foo class will be invoked and there all I'm doing is return super == other that means Object's == operator is being invoked and the other is int, so where the Foo instance in above code is? Here, it is only Object and int. I think super is doing something else too, not sure what is.
To answer your questions:
You can't do this == super because super is not an expression which is explained if you try run the program (the analyzed could give a better explanation):
bin/stackoverflow.dart:7:19: Error: Can't use 'super' as an expression.
To delegate a constructor to a super constructor, put the super call as an initializer.
print(this == super); // Compile error
^^^^^
Which also make sense since super is not an object. It is a concept we can use to specify if we want to refer to fields/methods that are overridden. But we cannot use super as some kind of object since our object is not multiple objects in layers where you can extract a layer and then represent this as another object. Instead, our object is a combined implementation based on how you define your class.
Yes, you're basically calling the Object's == operator when you return super == other.
Supplementary example:
But remember, we are just calling the == operator defined in Object. Our object is still a combined data structure which can be illustrated by this example:
class A {
final int a = 5;
int getA() => a;
}
class B extends A {
int get a => 10;
int getA() {
return super.getA();
}
}
void main() {
print(B().getA()); // 10
}
You can see that even if we call super.getA() we are still operating on a B object where we have overridden the a field but we are calling the A.getA() method.
I wrote service for manual requeuing events from one queue to another.
public class ReQueueService {
private final RabbitTemplate rabbitTemplate;
public void retry() {
InfoLog infoLog;
while (rabbitTemplate != null &&
(infoLog = (InfoLog) rabbitTemplate.receiveAndConvert(EVENT_WAITING_FOR_REQUEUE)) != null
) {
rabbitTemplate.convertAndSend(SOME_QUEUE, infoLog.getSomeEvent());
}
}
}
The problem I am facing is getting:
Too many invocations for:
1 * rabbitTemplate.convertAndSend(SOME_QUEUE, _ as SomeEvent) >> {
arguments ->
assert infoLog.getSomeEvent() == arguments[1]
} (2 invocations)
Matching invocations (ordered by last occurrence):
2 * rabbitTemplate.convertAndSend(SOME_QUEUE, ...
while my code in test looks like this:
class ReQueueServiceTest extends Specification {
def "should resend single event to some queue" () {
given:
InfoLog infoLog = Fixtures.createInfoLog()
def rabbitTemplate = Mock(RabbitTemplate){
receiveAndConvert(EVENT_WAITING_FOR_REQUEUE) >> { infoLog }
}
ReQueueService reSyncService = new ReQueueService(rabbitTemplate)
when:
reSyncService.retry()
then:
1 * rabbitTemplate.convertAndSend(SOME_QUEUE, _ as SomeEvent) >> {
arguments ->
assert infoLog.getSomeEvent() == arguments[1]
}
}
}
The question is why I have 2 invocations, if I stubb only one event?
EDIT:
link to repo with example: https://gitlab.com/bartekwichowski/spock-too-many
Thanks for the repo link. As soon as I could run the test and inspect the behaviour live, it was pretty easy to find out what was wrong. First I will make an educated guess about what you actually want to test:
The mock's receiveAndConvert method should return str when it is called first and then null when called again.
Subsequently you want to verify that the while loop runs exactly 1 iteration, i.e. that convertAndSend is called with exactly the parameters you expect.
This can be achieved by
receiveAndConvert("FOO") >>> [str, null]
1 * rabbitTemplate.convertAndSend("BAR", str) (no need for ugly assertions inside a stubbed method, the parameters are verified against your parameter constraints already)
If I refactor your specification a little bit for prettier variable names and less verbosity, it looks like this:
class ReSyncServiceTest extends Specification {
def "should resend single event to resource sync queue"() {
given:
def message = "someValue"
def rabbitTemplate = Mock(RabbitTemplate) {
receiveAndConvert("FOO") >>> [message, null]
}
when:
new ReSyncService(rabbitTemplate).retry()
then:
1 * rabbitTemplate.convertAndSend("BAR", message)
}
}
P.S.: Your version with the assertion inside does not return anything explicitly, but implicitly the result of the last assertion. Be careful with that. With >> { ... } you are stubbing the method result! It would always return true in the version you have in Git and the test only terminates because you added the 1 * limit. If it was not there, you would have an endless loop. Your code did not do what you thought it did. Maybe the Spock manual can help you there. :-)
P.P.S.: Maybe you want to refactor your application code to be a bit easier to understand and maintain and to be a little less "smart". Also there is no need to check that rabbitTemplate != null in every iteration, once should be enough. How about this?
#Slf4j
#Service
#AllArgsConstructor
public class ReSyncService {
private final RabbitTemplate rabbitTemplate;
public void retry() {
if (rabbitTemplate == null)
return;
String event;
while (null != (event = getEventFromQueue()))
rabbitTemplate.convertAndSend("BAR", event);
}
protected String getEventFromQueue() {
return (String) rabbitTemplate.receiveAndConvert("FOO");
}
}
I am stuck somewhere in Grails 3 spock Testing for Taglibs.
I want to test a closure of taglib, which looks like:
ATagLib.groovy:
Closure a = {attrs ->
java.util.TimeZone utc = java.util.TimeZone.getTimeZone(FraudnetConstants.TIMEZONE_UTC)
if (attrs.somevar) {
out << "${g.message(code: 'some.code')} ${g.formatDate([date: attrs.date, format: "h:mma", timeZone: utc])}"
} else if (attrs.freq == SomeConstants.VAL || attrs.freq == SomeConstants.VAL) {
out << g.formatDate([date: attrs.date, format: "E '#' h:mma", timeZone: utc])
} else {
out << "${g.message(code: 'some.other.code')} ${g.formatDate([date: attrs.date, format: "h:mma", timeZone: utc])}"
}
}
My ATagLibSpec.groovy looks like:
#TestFor(ATagLib)
class ATagLibSpec {
def setup() {
java.util.TimeZone.metaClass.'static'.getTimeZone = {a -> return null }
}
void 'testmethod'() {
expect:
taglib.a()
}
}
The exception i am getting while running testcases is:
java.lang.NullPointerException: Cannot invoke method getTimeZone() on null object at org.grails.plugins.web.taglib.FormatTagLib$_closure2.doCall(FormatTagLib.groovy:170) at groovy.lang.Closure.call(Closure.java:414)
at org.grails.taglib.TagOutput.captureTagOutput(TagOutput.java:64)
at org.grails.taglib.TagLibraryMetaUtils.methodMissingForTagLib(TagLibraryMetaUtils.groovy:138)
at org.grails.taglib.NamespacedTagDispatcher.methodMissing(NamespacedTagDispatcher.groovy:59)
Can someone point here, what's wrong with the above way of prepopulating getTimeZone.
instead of using metaprogramming, it is best to inject a TimezoneFactoryService into your taglib. Having to metaprogram in a test is in my experience an indication of code smell: your code uses a static method to instantiate an object, instead of dependency injection.
Your code could look like this:
Closure a = {attrs->
java.util.TimeZone utc = timezoneFactoryService.getTimeZone(FraudnetConstants.TIMEZONE_UTC)
}
This will allow you to mock your factory service in your spec in a way more convenient way, by using a regular Spock Mock.
#TestFor(ATagLib)
class ATagLibSpec {
def setup() {
taglib.timezoneFactoryService=Stub(TimezoneFactoryService) {
getTimeZone(_) >> null
}
}
void 'testmethod'() {
expect:
taglib.a()
}
}
If you still want to use metaprogramming, be aware that the signature of the method has to match fully (also the parameter types), so:
java.util.TimeZone.metaClass.'static'.getTimeZone = {a -> return null }
java.util.TimeZone.getTimeZone("America/Los_Angeles")
This code will get the timezone for America/Los Angeles, but
java.util.TimeZone.metaClass.'static'.getTimeZone = {String a -> return null }
java.util.TimeZone.getTimeZone("America/Los_Angeles")
this one will return null as we have modified the method properly via metaprogramming.
Be also aware that you have to use the injected variable tagLib not taglib.
I have some Java stuff like this:
public interface EventBus{
void fireEvent(GwtEvent<?> event);
}
public class SaveCommentEvent extends GwtEvent<?>{
private finalComment oldComment;
private final Comment newComment;
public SaveCommentEvent(Comment oldComment,Comment newComment){
this.oldComment=oldComment;
this.newComment=newComment;
}
public Comment getOldComment(){...}
public Comment getNewComment(){...}
}
and test code like this:
def "...."(){
EventBus eventBus=Mock()
Comment oldComment=Mock()
Comment newCommnet=Mock()
when:
eventBus.fireEvent(new SaveCommentEvent(oldComment,newComment))
then:
1*eventBus.fireEvent(
{
it.source.getClass()==SaveCommentEvent;
it.oldComment==oldComment;
it.newComment==newComment
}
)
}
I want to verify that the eventBus.fireEvent(..) gets called once with an Event with type SaveCommentEvent and construction parameters oldComment and newComment.
Code runs without errors but problem is:
After changing closure stuff from
{
it.source.getClass()==SaveCommentEvent;
it.oldComment==oldComment; //old==old
it.newComment==newComment //new==new
}
To
{
it.source.getClass()==Other_Class_Literal;
it.oldComment==newComment; //old==new
it.newComment==oldComment //new==old
}
Still, code runs without error? Apparently the closure didn't do what I want, so the question is: How to do argument capturing?
I got it:
SaveCommentEvent firedEvent
given:
...
when:
....
then:
1 * eventBus.fireEvent(_) >> {arguments -> firedEvent=arguments[0]}
firedEvent instanceof SaveModelEvent
firedEvent.newModel == newModel
firedEvent.oldModel == oldModel
then:
1*eventBus.fireEvent(
{
it.source.getClass()==SaveCommentEvent;
it.oldComment==oldComment;
it.newComment==newComment
}
)
In your code it is a Groovy Closure Implicit Variable reference to a mock eventBus Interface which has no fields. How could you verify them?
Also, I think the order of events that has to happen to use Spock Mocks is not necessarily intuitive. I would write it up here except it would not be as good as Kenneth Kousen's explanation.
Same idea with #Alex Luya but put the assertions in the closure and use assert on each of them. cf. Spock Framework Reference Documentation.
then:
1 * eventBus.fireEvent(_) >> {
def firedEvent = it[0]
assert firedEvent instanceof SaveModelEvent
assert firedEvent.newModel == newModel
assert firedEvent.oldModel == oldModel
}
In 2021 (7 yrs later) it is possible to do the following with groovy (2.5):
...
then:
1 * eventBus.fireEvent(_) >> { SaveModelEvent event ->
assert event.newModel == newModel
assert event.oldModel == oldModel
}
0 * _
.. which feels more handy to me and saves a line or two. :)
If you want to mock a method's response and also verify the same method's params(same as capturing the params), you can use Spock's code constraints (among other constraints) to partially match params, and at the same time, verify the method params. :
1 * list.add({
verifyAll(it, Person) {
firstname == 'William'
lastname == 'Kirk'
age == 45
}
}) >> mockedResponse
PS: Solution inspired by this response from #Leonard Brünings
In the answer from #alex-luya above, I found that the variable firedEvent needs the #Shared annotation.
Then I can capture the value and run my checks on the value outside the closure.
I have two class:
class Foo {
String doSomething(String a = 'Not working') {
return a
}
}
And I want to replace 'doSomething' in a test but it dosent work
#Test
void testMethodIWannaTest() {
Foo.metaClass.doSomething = {String a -> return 'Working'}
assert new Foo().doSomething() == 'Working' //THIS TEST FAIL, return 'Not Working'
}
If I remove the optional param, it works.
Did someone know how to fix this ?
*I know the test doesn't really make sens, it's just to show my point
What do I do wrong ? Is it possible to do it without using 'mockFor' ?
Setting a default parameter generates two methods:
String doSomething() { doSomething( 'Not working' ) }
String doSomething(String a) { a }
So try setting the no-arg function (as that's the one you're going to call:
Foo.metaClass.doSomething = { -> doSomething( 'Working' ) }