For a case in which stubbed variable in made inside the actual production code,
How can we pass actual arguments with stubbing e.g using Mockito.when in JUnits?
E.g if a method in production code is like:
1) servicaClass.doSomething(Calendar.getInstance)
2) servicaClass.doSomething(someMethodToCreateActualVariable())
while testing how a actual parameter can be passed?
Like
-> when(mockedServiceClass.doSomething(Calendar.geInstance)).thenReturn("")
But while testing production code will take its own calendar value while executing.
There can be a way to make public setter getter method for the used variable to be stuffed. But that dont seem to be a optimum solution.
Any pointers with this regard will be helpful?
If you know the matching value before the fact, you can use stubbing. Mockito matchers like eq (compare with equals) and same (compare with ==) will help there, or you can get the eq behavior by specifying the value directly. Note that you have to use Matchers for all values if you use any at all; you can't use Matchers for only one argument of a two-argument method call.
// Without matchers
when(yourMock.method(objectToBeComparedWithEquals))
.thenReturn(returnValue);
// With matchers
when(yourMock.method(eq(objectToBeComparedWithEquals)))
.thenReturn(returnValue);
when(yourMock.method(same(objectToBeComparedReferentially)))
.thenReturn(returnValue);
If you don't know the matching value until after you run the method, you might want verification instead. Same rules apply about Matchers.
SomeValue someValue = yourSystemUnderTest.action();
verify(yourMock).initializeValue(someValue);
And if you need to inspect the value after the fact, you can use a Captor:
ArgumentCaptor myCaptor = ArgumentCaptor.forClass(SomeValue.class);
yourSystemUnderTest.action();
verify(yourMock).initializeValue(myCaptor.capture());
SomeValue valueMockWasCalledWith = myCaptor.getValue();
// Now you've retrieved the reference out of the mock, so you can assert as usual.
assertEquals(42, valueMockWasCalledWith.getInteger());
Related
I'm writing a test case to validate execution with specific method call with specific arguments. The test need to pass only when specific values are passed (for ex. only pass when status & ParseError is passed) to the method. Below is the code snippet for the test to verify:
Mockito.verify(exeImpl, Mockito.atLeastOnce()).setData(eq("status"), eq("ParseError"));
and case failed with below:
Argument(s) are different! Wanted:
exeImpl.setData(
"status",
"ParseError"
);
-> at com.TestTask.testRest(TestTask.java:280)
Actual invocation has different arguments:
exeImpl.setData(
"status",
"Error"
);
-> at
com.TestTask.setDefault(Task.java:186)
The actual invocation which is mentioned in the error is because the setData is called with default values before starting the business logic. After the business logic is done, the setData is called again to set the result.
And setData has below definition
setData(final String arg1, final Object arg2) {...}
I know about ArgumentCaptor, but I'm just trying to make it work like this as i believe the matcher eq() is used here to check the equals of the value passed for both the arguments. Or is it causing issue because it is object.
Will it be possible to verify like this? Thanks.
The issue was with my code as my test was not initialized properly with #Before.
I'm trying to verify that the class I'm testing calls the correct dependency class's method. So I'm trying to match the method parameters, but I don't really care about the actual values in this test, because I don't want to make my test brittle.
However, I'm running into trouble setting it up because Mockito has decided that the behaviour I'm expecting is a bug: https://github.com/mockito/mockito/issues/134
So what't the correct way to define an ArgumentMatcher for a parameter that might be null?
With issue #134 "fixed", this code fails because the matchers only match in the first case. How can I define a matcher to work in all 4 cases?
MyClass c = mock(MyClass.class);
c.foo("hello", "world");
c.foo("hello", null);
c.foo(null, "world");
c.foo(null, null);
verify(c, times(4)).foo(anyString(), anyString());
From the javadocs of any()
Since Mockito 2.1.0, only allow non-null String. As this
is a nullable reference, the suggested API to match
null wrapper would be isNull(). We felt this
change would make tests harness much safer that it was with Mockito
1.x.
So, the way to match nullable string arguments is explicit declaration:
nullable(String.class)
I got this to work by switching to any(String.class)
I find this a bit misleading, because the API seems to suggest that anyString() is just an alias for any(String.class) at least up till the 2.0 update. To be fair, the documentation does specify that anyString() only matches non-null strings. It just seems counter-intuitive to me.
How about:
verify(c, times(4)).foo(anyObject(), anyObject());
Does that work for you?
Matchers.anyObject() allows for nulls.
Reference in Mockito docs:
Using Mockito I got in trouble with the following:
Mockito.when(restOperationMock.exchange(
Mockito.anyString(),
Mockito.any(HttpMethod.class),
Mockito.any(HttpEntity.class),
Mockito.eq(CustomerResponse.class),
**Mockito.anyMap()**)).
thenReturn(re);
The problem was the method wasn't intercepted because I was using Mockito.any(Map.class) instead of Mockito.anyMap() and I was passing as a parameter a HashMap. What are the differences between Mockito.any(Map.class) and Mockito.anyMap()?
There is only one small difference between any(Map.class) and anyMap(): Starting with Mockito 2.0, Mockito will treat the any(Map.class) call to mean isA(Map.class) rather than ignoring the parameter entirely. (See the comment from Mockito contributor Brice on this SO answer.) Because restOperationMock.exchange takes an Object vararg, you may need anyMap to catch a case where a non-Map object is being passed, or no object at all is passed.
(I'd previously put that as a "dummy value" to return, Mockito can return an empty Map for calls to anyMap(), but can only return a null for calls to any(Map.class). If restOperationMock.exchange delegates to a real implementation during stubbing, such as if it were a spy or unmockable method (final method, method on a final class, etc), then that dummy value may be used in real code. However, that's only true for any(); anyMap() and any(Map.class) both give Mockito enough information to return a dummy Map implementation, where any() has its generics erased and only knows enough to return null.)
To illustrate the following example I created a litte spock test (but it's about groovy itself, not spock):
void "some spock test"() {
given: String value = null
expect: someMethod(value) == 3
}
int someMethod(String s) {
return 3
}
int someMethod(Map s) {
return 5
}
There are two methods who's signatures only differ by the type of the given parameter. I thought that when I give it a null value that is explicitly typed as a string, the string-method will be called.
But that doesn't happen; the test fails, because the map-method is called! Why?
I guess groovy ignores the type and treats all nulls the same. There seems to be some kind of priority of types: When I use Object instead of Map as the parameter type of the wrong-method, its all the same, but when I for instance use Integer, the test succeeds.
But than again: If groovy really ignores the type of nulls, why can the following fix the original test:
expect: someMethod((String) value) == 3
If you read my answer to the question Tim already mentioned you will see that I talk there about runtime types. The static type plays normally no role in this. I also described there how the distance calculation is used and that for null the distance to Object is used to determine the best fitting method. What I did not mention is that you can force method selection by using a cast. Internally Groovy will use a wrapper for the object, that also transports the type. Then the transported type is used instead. But you surely understand, that this means a one additional object creation per method class, which is very inefficient. Thus it is not the standard. In the future Groovy maybe change to include that static type information, but this requires a change to the MOP as well. And that is difficult
I have a method which return array of object.
public IConfigurationElement[] getConfigurationElementsFor(String extensionPointId);
I am not sure how can I mock this call using mockito and powermock.
I have tried
mockConfigurationElements = (IConfigurationElement[]) Mockito.anyListOf( IConfigurationElement.class ).toArray();
but this is ending in ClassCastException.
Mocking (stubbing) calls with Mockito is done in a following way (for example):
Mockito.when(mockObject.getConfigurationElementsFor(Mockito.anyString()).thenReturn(new IConfigurationElement[]{})
or
Mockito.doReturn(new IConfigurationElement[]{}).when(mockObject).getConfigurationElementsFor(Mockito.anyString());
Mockito.anyListOf() is a use of a matcher. Matchers are passed instead of real arguments when stubbing meaning that the behavior is to be applied if the method is called with arguments satisfying those matchers.