Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to mock a generic parameter for a unit test in Java?

I have a function signature I'd like to mock of an External Service.

public <T> void save(T item, AnotherClass anotherClassObject);

Given this function signature, and class name IGenericService how could one mock it with PowerMock? Or Mockito?

For this generic, I'm using: Class Theodore for the T in T item. For example, I tried using:

doNothing().when(iGenericServiceMock.save(any(Theodore.class),
                    any(AnotherClass.class));

IntelliJ cranks this:

save(T, AnotherClass) cannot be applied to 
(org.Hamcrest.Matcher<Theodore>, org.Hamcrest.Matcher<AnotherClass>)

And it cites the following reason:

reason: No instance(s) of type variable T exist 
so that Matcher<T> conforms to AnotherClass

First, the issue ought to solve if the generics argument is handled properly. What are some things one could do in such situations?

UPDATE: As ETO shared:

doNothing().when(mockedObject).methodToMock(argMatcher); 

shares the same fate.

like image 813
Rohan Kumar Avatar asked Jun 15 '26 17:06

Rohan Kumar


2 Answers

You are passing wrong parameters to when. It may be a bit confusing, but there are two different usages of when method (actually those are two different methods):

  1. when(mockedObject.methodYouWantToMock(expectedParameter, orYourMatcher)).thenReturn(objectToReturn);
    
  2. doReturn(objectToReturn).when(mockedObject).methodYouWantToMock(expectedParameter, orYourMatcher);
    

Note: pay attention to input parameters of when method in both cases.

In your particular case you could do something like this:

doReturn(null).when(iGenericServiceMock).save(any(Theodore.class), any(AnotherClass.class));

This will fix your compilation issues. However the test will fail at runtime with org.mockito.exceptions.misusing.CannotStubVoidMethodWithReturnValue because you are trying to return something from a void method (null is not void). What you should do is :

doNothing().when(iGenericServiceMock).save(any(Theodore.class), any(AnotherClass.class));

Later you can check the interactions with your mock using verify method.

UPDATE:

Check your imports. You should use org.mockito.Matchers.any instead of org.hamcrest.Matchers.any.

like image 148
ETO Avatar answered Jun 17 '26 05:06

ETO


Try to use the Mockito's ArgumentMatcher. Also in when put only the mock's reference:

doReturn(null).when(iGenericServiceMock).save(
    ArgumentMatchers.<Theodore>any(), ArgumentMatchers.any(AnotherClass.class));
like image 36
Maciej Kowalski Avatar answered Jun 17 '26 05:06

Maciej Kowalski



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!