My getUserDetails class take User(custome class) and string as arguments and return User. If I use Mockito matcher as below:
when(authService.getUserDetails(any(User.class),anyString())).thenReturn(any(User.class));
It gives me InvalidUseOfMatchersException 2 matchers expected, 3 found. Can't I use the above expression?
Matchers are not used for returning.
.thenReturn(any(User.class));
You have to return something tangible here. Matchers are just for matching up input so that you can dictate what is returned when certain input is provided. You still need to have a real output to return.
You should pass instance of User to thenReturn, not matcher. That User instance will be returned when authService.getUserDetails is invoked.
This code will work:
User user=new User();
when(authService.getUserDetails(any(User.class),anyString())).thenReturn(user));
As there should be a value and not type in thenReturns()
Related
I want to test a method which accepts list of string, makes a database call and returns list of entities.
EmployeeServiceTest
when(repository
.findByMessageTypeAndStatusAndMobileInOrderByCreatedDate("confirmed",
"received", anyList(), new PageRequest(0, 1000)))
.thenReturn(employeeEntities);
It gives below exception. matching the stringList with anyList() seems to be causing exception.
org.mockito.exceptions.misusing.InvalidUseOfMatchersException:
You cannot use argument matchers outside of verification or stubbing.
Examples of correct usage of argument matchers:
when(mock.get(anyInt())).thenReturn(null);
doThrow(new RuntimeException()).when(mock).someVoidMethod(anyObject());
verify(mock).someMethod(contains("foo"))
Also, this error might show up because you use argument matchers with methods that cannot be mocked.
Following methods *cannot* be stubbed/verified: final/private/equals()/hashCode().
Mocking methods declared on non-public parent classes is not supported.
anyList() to match List of string is causing the exception. any idea why the exception is caused?
Probably your employeeService does not contain a mocked EmployeeService.
Create it by calling
EmployeeService employeeService = mock(EmployeeService.class)
instead of instantiating the real class (do not use new EmployeeService() here).
Update after the question has been extended:
You are mixing how arguments are matched: the first, second and fourth parameter are plain objects but the third parameter is a matcher.
If you verify one argument with a matcher, you have to use them for every argument.
There are matchers which are not wildcards but check whether the argument is equal to a fixed value: wrap your other arguments in the eq matcher:
when(repository .findByMessageTypeAndStatusAndMobileInOrderByCreatedDate(
eq("confirmed"),
eq("received"),
anyList(),
eq(new PageRequest(0, 1000))
)).....
Notice you have to implement a proper equals method in the class PageRequest. Otherwise org.mockito.Matchers.eq cannot compare the parameters successfully.
I am new to Mockito and trying to cover following source code:
jdbcOperations.update(insertRoleQuery,new Object[]{"menuName","subMenuName","subSubMenuName","aa","bb","cc","role"});
In this query is taking 7 string parameters. I have written the mockito test case for the code and it's also covering the source code but I am not sure whether it's the correct way or not.
when(jdbcOperations.update(Mockito.anyString(), new Object[]{Mockito.anyString(),Mockito.anyString(),Mockito.anyString(),Mockito.anyString(),Mockito.anyString(),Mockito.anyString(),Mockito.anyString()})).thenThrow(runtimeException);
Please suggest if i am doing it right way or not.
Thanks
As per the docs, you can either use exact values, or argument matchers, but not both at the same time:
Warning on argument matchers:
If you are using argument matchers, all arguments have to be provided
by matchers.
If you do mix them, like in your sample, mockito will complain with something similar to
org.mockito.exceptions.misusing.InvalidUseOfMatchersException:
Invalid use of argument matchers!
2 matchers expected, 1 recorded:
-> at MyTest.shouldMatchArray(MyTest.java:38)
This exception may occur if matchers are combined with raw values:
//incorrect:
someMethod(anyObject(), "raw String");
When using matchers, all arguments have to be provided by matchers.
For example:
//correct:
someMethod(anyObject(), eq("String by matcher"));
For more info see javadoc for Matchers class.
In your case you don't seem to care about the array contents, so you can just use any():
when(jdbcOperation.update(anyString(), any())).thenThrow(runtimeException);
If you want to at least check the number of parameters, you can use either
org.mockito.Mockito's argThat(argumentMatcher):
when(jdbcOperation.update(anyString(), argThat(array -> array.length == 7))).thenThrow(runtimeException);
org.mockito.hamcrest.MockitoHamcrest's argThat(hamcrestMatcher):
when(jdbcOperation.update(anyString(), argThat(arrayWithSize(7)))).thenThrow(runtimeException);
If you're interested in matching certain values, you can use AdditionalMatchers.aryEq(expectedArray), or just Mockito.eq(expectedArray) which has a special implementation for arrays, but I fell that the first one expresses your intent in a clearer way.
when(jdbcOperation.update(anyString(), aryEq(new Object[]{"whatever"}))).thenThrow(runtimeException);
I have a method which needs to be called instead of the real method.
Instead I get an exception. Can somebody please help me with right way to call the alternate method through mockito ?
org.mockito.exceptions.misusing.InvalidUseOfMatchersException:
Invalid use of argument matchers!
2 matchers expected, 4 recorded.
This exception may occur if matchers are combined with raw values:
//incorrect:
someMethod(anyObject(), "raw String");
When using matchers, all arguments have to be provided by matchers.
For example:
//correct:
someMethod(anyObject(), eq("String by matcher"));
//Code starts here
class A{
public realMethod(String s, Foo f){
}
}
class B {
public mockMethod(String s, Foo f) {
}
}
class UnitTestClass{
ClassA mock = new ClassA();
mock.when(realMethod(any(String.class), any(Foo.class))).thenReturn(mockMethod(any(String.class),any(Foo.class));
}
You are getting mocking wrong.
Here:
thenReturn(mockMethod(any(String.class),any(Foo.class));
That simply doesn't make sense.
Mocking works like this:
you create a mock object of some class, like A mock = mock(A.class)
you specify interactions on that mock object
Your code implies that you think that these specifications are working like "normal" code - but they do not!
What you want to do: when some object is called with certain parameters, then return the result of another method call.
Like in:
when(a.foo(x, y)).thenReturn(b.bar(x, y))
That is what want you intend to do. But thing is: it isn't that easy. You can't use the any() matcher in thee thenReturn part in order to "provide" the arguments that were passed in the when() call before! It is that simply.
Mocking should be within a specific unit test to get a specific result.
Meaning: you are not writing an ordinary program where it would make any sense to "forward" parameters to another call. In other words; your code should more look like:
when(mock.realMethod("a", someSpecificFoo)).thenReturn(mockMethod("a", someSpecificFoo))
That is the only thing possible here.
Beyond that, you might want to look into a Mockito enter link description here instead.
Long story short: it simply looks like you don't understand how to use mocking frameworks. I suggest that you step back and read/work various tutorials. This is not something you learn by trial and error.
I am testing a Restful endpoint in my JUnit and getting an exception as below in the
list which is present as an argument inside the save method,
**"Argument(s) are different! Wanted:"**
save(
"121",
[com.domain.PP#6809cf9d,
com.domain.PP#5925d603]
);
Actual invocation has different arguments:
save(
"121",
[com.domain.PP#5b6e23fd,
com.domain.PP#1791fe40]
);
When I debugged the code, the code broke at the verify line below and threw the
above exception. Looks like the arguments inside the "testpPList" within the save
method is different. I dont know how it becomes different as I construct them in my
JUNit properly and then RestFul URL is invoked.
Requesting your valuable inputs. Thanks.
Code:
#Test
public void testSelected() throws Exception {
mockMvc.perform(put("/endpointURL")
.contentType(TestUtil.APPLICATION_JSON_UTF8)
.content(TestUtil.convertObjectToJsonBytes(testObject)))
.andExpect(status().isOk());
verify(programServiceMock, times(1)).save(id, testpPList);
verifyNoMoreInteractions(programServiceMock);
}
Controller method:
#RequestMapping(value = "/endpointURL", method = RequestMethod.PUT)
public #ResponseBody void uPP(#PathVariable String id, #RequestBody List<PPView> pPViews) {
// Code to construct the list which is passed into the save method below
save(id, pPList);
}
Implementing the Object#equals(Object) can solve it by the equality comparison. Nonetheless, sometimes the object you are validating cannot be changed or its equals function can not be implemented. For such cases, it's recommended using org.mockito.Matchers#refEq(T value, String... excludeFields). So you may use something like:
verify(programServiceMock, times(1)).save(id, refEq(testpPList));
Just wrapping the argument with refEq solves the problem.
Make sure you implement the equals method in com.domain.PP.
[Edit]
The reasoning for this conclusion is that your failed test message states that it expects this list of PP
[com.domain.PP#6809cf9d, com.domain.PP#5925d603]
but it's getting this list of PP
[com.domain.PP#5b6e23fd, com.domain.PP#1791fe40]
The hex values after the # symbol for each PP object is their hash codes. Because they are different, then it shows that they belong to different objects. So the default implementation of equals will say they're not equal, which is what verify() uses.
It's good practice to also implement hashCode() whenever you implement equals(): According to the definition of hashCode, two objects that are equal MUST have equal hashCodes. This ensures that objects like HashMap can use hashCode inequality as a shortcut for object inequality (here, placing objects with different hashCodes in different buckets).
List<Populate> fullAttrPopulateList = getFullAtrributesPopulateList(); //Prepare return list
when(mockEmployeeDao.getPopulateList(null)).thenReturn(fullAttrPopulateList);
MyDTO myDto = testablePopService.getMyPopData(); //Will call mockEmployeeDao.getPopulateList(null)
//verify(mockEmployeeDao,times(1)).getPopulateList(null);
assertEquals(fullAttrPopulateList.size(), myDto.getPopData().size()); //This fails because myDto.getPopData().size() returns 0
As you can see testablePopService.getMyPopData() calls mockEmployeeDao.getPopulateList(null) but when I debug it a zero sized list returns instead of the stubbed array list which is prepared by getFullAtrributesPopulateList();
If I uncomment the verify statement, it passes the test meaning getPopulateList(null) behavior does get called.
Can anyone give me some advice why my stubbed array list cannot be returned even it is verified the expected behavior happened? How come an empty array list returns rather than a null if I did something wrong?
First, check that the method is non-final and visible throughout its hierarchy. Mockito can have trouble mocking methods that are hidden (e.g. overriding a package-private abstract class's implementation); also, Mockito is entirely unable to mock final methods, or even to detect that the method is final and warn you about it.
You may also want to check that your call is using the overload you expect. Mockito's default list return value is an empty list, so you may simply stubbing one method and seeing the default value for another. You can see which method interactions Mockito has added by adding a call to verifyZeroInteractions temporarily, and Mockito will throw an exception with a list of calls that mock has received. You could also add verifyNoMoreInteractions, and even leave it in there, at the expense of test brittleness (i.e. the test breaks when the actual code continues to work).