Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Stubbing a method that takes Class<T> as parameter with Mockito

There is a generic method that takes a class as parameter and I have problems stubbing it with Mockito. The method looks like this:

public <U extends Enum<U> & Error, T extends ServiceResponse<U>> T validate(     Object target, Validator validator, Class<T> responseClass,     Class<U> errorEnum); 

It's god awful, at least to me... I could imagine living without it, but the rest of the code base happily uses it...

I was going to, in my unit test, stub this method to return a new empty object. But how do I do this with mockito? I tried:

when(serviceValidatorStub.validate(     any(),      isA(UserCommentRequestValidator.class),      UserCommentResponse.class,      UserCommentError.class) ).thenReturn(new UserCommentResponse()); 

but since I am mixing and matching matchers and raw values, I get "org.mockito.exceptions.misusing.InvalidUseOfMatchersException: Invalid use of argument matchers!"

like image 703
Peter Perháč Avatar asked Mar 28 '11 16:03

Peter Perháč


People also ask

What does stubbing mean in Mockito?

A stub is a fake class that comes with preprogrammed return values. It's injected into the class under test to give you absolute control over what's being tested as input. A typical stub is a database connection that allows you to mimic any scenario without having a real database.

How do you use argument matchers in Mockito?

Mockito uses equal() as a legacy method for verification and matching of argument values. In some cases, we need more flexibility during the verification of argument values, so we should use argument matchers instead of equal() method. The ArgumentMatchers class is available in org. mockito package.

What can I use instead of Mockito matchers?

mockito. Matchers is deprecated, ArgumentMatchers should be used instead.

Can Mockito mock a class?

The Mockito. mock() method allows us to create a mock object of a class or an interface. We can then use the mock to stub return values for its methods and verify if they were called.


2 Answers

The problem is, you cannot mix argument matchers and real arguments in a mocked call. So, rather do this:

when(serviceValidatorStub.validate(     any(),     isA(UserCommentRequestValidator.class),     eq(UserCommentResponse.class),     eq(UserCommentError.class)) ).thenReturn(new UserCommentResponse()); 

Notice the use of the eq() argument matcher for matching equality.

see: https://static.javadoc.io/org.mockito/mockito-core/1.10.19/org/mockito/Matchers.html#eq(T)

Also, you could use the same() argument matcher for Class<?> types - this matches same identity, like the == Java operator.

like image 172
Jesse Avatar answered Oct 03 '22 08:10

Jesse


Just in order to complete on the same thread, if someone want to stubb a method that takes a Class as argument, but don't care of the type, or need many type to be stubbed the same way, here is another solution:

private class AnyClassMatcher extends ArgumentMatcher<Class<?>> {      @Override     public boolean matches(final Object argument) {         // We always return true, because we want to acknowledge all class types         return true;     }  }  private Class<?> anyClass() {     return Mockito.argThat(new AnyClassMatcher()); } 

and then call

Mockito.when(mock.doIt(this.anyClass())).thenCallRealMethod(); 
like image 42
Ash Avatar answered Oct 03 '22 08:10

Ash