Here is a very beginner's question:
The class that I mock, has methods Map<String, Integer>methodA(String p1,String p2,String p3, SomeClass p4) and MyClass methodB(String p1,String p2,String p3)
methodA internally calls methodB:
Map<String, Integer> methodA(String p1, String p2, String p3, SomeClass p4){
MyClass data = methodB(p1,p2,p3);
.... do something
... return Map.
}
I am stubbing the methodB.
when(mockedTestClass.methodB(p1, p2, p3, null)).thenReturn(myData);
I use null for the fourth argument since SomeClass is an abstract class.
When I call the stubbed method in the test directly with p1, p2 p3 and null (p4) arguments, it returns the correct mock data (an instance of MyClass).
However, if I call methodA, it seems that methodB is not getting called and I get empty Map (not null) returned.
What would cause this?
Thank you in advance,
Yuri.
If I understand correctly, you have a class you're mocking, ClassA, that has two methods, method1 and method2. And you know that ClassA.method1 happens to call method2 internally. And so you've only mocked method2, and left method1 with the default behavior, right?
So in that case, both methods are actually mocked, you're mocking at the class level not the method level. When you do a when you're saying, "I want this method to return this exact result in this specific case. If you don't use when then the method is an empty mock returning a null or empty value for the type that it returns. It's assumed if you don't specify you don't care.
So given that, you should see that method1 when the class is mocked does not actually call method2. Both methods are mocked and only a direct call to method2 will return the result of your when matcher.
Also, when is used to ensure a specific result is returned when a method is called. If you want to verify that a certain method was actually called with specific parameters, you can do that like this:
verify(mockedClass).someMethod(p1, p2, p3, null); // <- or use matchers for the parameters
Related
I have a superclass called A and a subclass called B that inherits from A. The superclass's constructor looks like this:
A(String name, char displayChar, int hitPoints, Behaviour behaviour)
{
this.name = name;
this.displayChar = displayChar;
this.hitPoints = hitPoints
addBehaviour(behaviour);
}
A has attributes of name, displayChar, hitPoints, behaviour and has a method that calls addBehaviour which adds the behaviour to the object.
The subclass, B's constructor looks like this:
B(String name) {super(name, char 'b', 10, new WalkBehaviour()); }
Now my question is, does subclass B have an attribute of WalkBehaviour?
How would the UML diagram look like for this scenario? I know B inherits from A and A has Behaviour but does B has WalkBehaviour in this case? Since B doesn't have an instance variable of type WalkBehaviour in its class but only passes WalkBehaviour through its superclass's constructor.
does subclass B have an attribute of WalkBehaviour?
No. There is none declared. The superclass will do something with that new object but obviously it's hidden in the mist of its implementation.
Inheritance is nothing that involves multiple object creation. Your B instance is just a single one which does have attributes and operations like its super class.
Thus, in a SD, you will see only one life line for B:
As you can see the B instance will just issue a self-call to the super class's constructor.
Note: as #AxelScheithauer pointed out in the comment the super class will invoke addBehavior which can (but must not) be shown in the SD:
Some Context
When setting up mocks (when) or verifying calls (verify) on mocks, Mockito requires you to either provide all concrete values a mocked method needs, or provide a matcher for all of them. It is not possible to mix these styles.
when(mock.method(1, 2, 3));
when(mock.method(eq(1), eq(2), eq(3)));
I am talking about the second style.
Because of the way Mockito works, the order in which matchers are called is important. Internally, Mockito will register the matchers on a stack, executing them in order when necessary.
What I try to achieve
I want to write some test utilities to be used with mockito. I would like these utility methods to delegate calls to the mock, interjecting some default matchers that would otherwise be boilerplate test code.
For example:
public String callOnMock(int argument2) {
return mock.call(eq(1), argument2, argThat(i -> i >= 3));
}
which would be used like this:
when(callOnMock(eq(2)).thenReturn("result");
The problem
This does not work because Mockito registers these matchers in the wrong order:
eq(2)
eq(1)
argThat(i -> i >= 3)
while it should be
eq(1)
eq(2)
argThat(i -> i >= 3)
Is there a way for me to manipulate the order that those matchers are registered?
I now that org.mockito.AdditionalMatchers has methods that manipulate the internal stack to allow matchers to be combined (and, or, not) so at least internally inside the Mockito core it is possible.
Is it also possible to pop and push matchers explicitly?
Use a Supplier :
public String callOnMock(Supplier<Integer> argument2) {
return mock.call(eq(1), argument2.get(), argThat(i -> i >= 3));
}
when(callOnMock(() -> eq(2)).thenReturn("result");
Try this:
public String callOnMock(int argument2) {
return mock.call(eq(1), eq(argument2), argThat(i -> i >= 3));
}
and call it like:
when(callOnMock(2)).thenReturn("result");
I think there are a couple of ways to achieve the desired behaviour.
1. Manipulate the order of matchers on the stack
This is not the way to go!
The matcherStack seems to be internal to Mockito.
They do have a method to pullLocalizedMatchers from the stack and a reportMatcher method to push an ArgumentMatcher onto the stack. These could be accessed via
org.mockito.internal.progress.ThreadSafeMockingProgress
.mockingProgress()
.getArgumentMatcherStorage()
So in theory you could choose this path, but the solution would be brittle because you are messing with the internals of Mockito. They could change without notice in subsequent versions of Mockito.
Luckily there are a couple of alternatives.
2. Control the order in which matchers are registered in the first place
Using the Java 8 Supplier functional interface (This corresponds to this answer given by #ToYonos)
Matchers are registered automatically by Mockito when you call the methods creating them (eq, argThat, any, isNotNull, ...). But you can delay calling these methods by passing a Supplier for each of those matchers. The convenience method then controls the order in which it executes those suppliers.
public String callOnMock(Supplier<Integer> argument2) {
return mock.call(eq(1), argument2.get(), argThat(i -> i >= 3));
}
when(callOnMock(() -> eq(2))).thenReturn("result");
Using it looks a bit different than the normal Mockito style.
Special care needs to be taken if you offer convenience methods for those suppliers that use/aggregate other matchers, because of the same problem.
callOnMock(() -> AdditionalMatchers.and(isNotNull(), eq(2)))
will work,
but this will not:
public Supplier<Integer> and(int matcher1, int matcher2){
return () -> AdditionalMatchers.and(matcher1, matcher2);
}
callOnMock(and(isNotNull(), eq(2)))
This puts some responsibility with the user of your methods. They have to make sure that none of the matchers gets called accidentally.
3. Control the order in which mocks expect matchers
Delegating mock calls to a different mock object can give you control over the order of the arguments.
You will have to define an interface that expects matchers in the order your convenience method receives them, putting the ones added by the convenience method at the end.
Expectations have to be made against that delegate interface.
public interface MockDelegate {
String call(Integer i1, Integer i0, Integer i2);
}
#Mock
private MockDelegate delegate;
#Before
public void setUp() {
when(mock.call(any(), any(), any()))
.thenAnswer(invocation -> delegate.call(
invocation.getArgument(1), // this delegates the call
invocation.getArgument(0), // but flips the first two arguments
invocation.getArgument(2)
));
}
public String callOnMock(int argument2) {
return delegate.call(argument2, eq(1), argThat(i -> i >= 3));
}
This can be used with normal Mockito style matchers:
when(callOnMock(eq(2))).thenReturn("result");
class ArgumentClass{
int var;
}
class ClassMocked{
int aMothod(ArgumentClass argumentClass){
return anInt;
}
}
class MyTest{
Mock and Stub here
}
In MyTest, I want to stub aMothod such that it returns the value basing on value of ArgumentClass.var. And I have to do it in one go.
In other words, I have a test case where a moehod is called three times by the app code and basing on a variable in an argument object, I need different return values. I need to stub accordingly. Please let me know if there is a way.
If I understand that correctly you can do it in two different way with mockito. If you declare ClassMocked as a mock you should be able to say this:
when(mock.aMothod(eq(specificArgument))).thenReturn(1);
when(mock.aMothod(eq(anotherSpecificArgument))).thenReturn(2);
If you want to do it that regardless of the argument passed you want to return values based on the number of invocation of the method you can say:
when(mock.aMothod(any())).thenReturn(1, 2);
This says that when aMothod is called regardless of the parameter passed (any()) it will return in the first call 1 and when called second time it will return 2.
Though you can have your mock return values in the right order, as in karruma's answer, you may also use an Answer to calculate the mocked value:
when(mock.aMothod(any())).thenAnswer(new Answer<Integer>() {
#Override public Integer answer(InvocationOnMock invocation) {
ArgumentClass argument = invocation.getArguments()[0];
return calculationBasedOn(argument);
}
});
Or in Java 8 and Mockito 2 beta (untested, may need boxing/unboxing casts):
when(mock.aMothod(any())).thenAnswer(invocation ->
calculatebasedOn(invocation.getArgumentAt(0, ArgumentClass.class)));
Though I have an anonymous inner class in the top sample, naturally, you can make a named Answer subclass and reuse it across your application.
Suppose I have this class:
class MyClass {
int myInt
MyClass(myInt) {
this.myInt = myInt
}
def myMethod() {
print this.myInt
}
}
And somewhere I have:
def myClass1 = new MyClass(1)
def myMethodClosure = myClass1.&myMethod
def myClass2 = new MyClass(2)
Now if I call myMethodClosure() it will call myMethod() on myClass1 instance which will print 1. What I want is to call the same myMethodClosure but on a different instance, in this case on myClass2 so it can print 2. Is this possible?
I have tried using setDelegate(), but it does not work. I have also seen that there is field thisObject inside the closure class, but it does not have a setter, only a getter.
There were two methods added to Groovy to aid serialization of Closures, dehydrate and rehydrate. Basically, they strip (and reconstruct) a Closure's owner, thisObject and delegate. In this example, you could do:
myMethodClosure.rehydrate( myClass2, myClass2, myClass2 )()
To get the output 2, however I'd be wary about doing this as it is not what the method was intended for and there could be serious unforeseen consequences.
A better solution would probably be to write a factory method that gets a method reference for the given instance of MyClass. There may be other -- better -- solutions, but it depends on the situation you are in (that I suspect is not shown by the example in the question)
I believe closure "includes" the enclosing object to act upon. It is not possible override "this" inside a closure at runtime.
Say I have a function
def method1(MyClass2 mc2) {...}
and I call it with an object of type MyClass1. Is there a way that I can specify how to implicitly convert from MyClass1 to MyClass2, so that the method call will work without having to explicitly say method1(mc1 as MyClass2)?
If MyClass1 doesn't implement/extend MyClass2, there isn't anything that I'm aware of that'll do the "as MyClass2" conversion without the old standby Java method overloading. Explicitly overloading the method with the signature including MyClass1:
def method1(MyClass1 mc1) {
method1(mc1 as MyClass2)
}
The other, more groovy, alternative is to not explicitly type method1 so that it doesn't demand that you have an instance of MyClass2:
def method1(mc) {
// do stuff and let mc walk/talk/quack like MyClass2
// or even do the "as MyClass2" in this method if you need it for something further down.
}