Geoff L. Geoff L. - 19 days ago 6
Java Question

How to JUNIT a java.util.Function using Mockito

I would like to perform a junit test using Mockito on the toEntity function.

@Component
public class MyEntityTransform {
public Function<MyDTO , MyEntity> toEntity = new Function<MyDTO , MyEntity >() {
@Override
public MyEntity apply(MyDTO record) {
return new MyEntity();
}
};
}


Unfortunately the toEntity is NULL when I mock the class and I don't know how I can test it correctly.

@RunWith(MockitoJUnitRunner.class)
public class MyTest {

@InjectMocks
private MyService _classUnderTest;

@Mock
private MyEntityTransform myEntityTransform

@Before
public void setUp() {
Mockito.when(this.myEntityTransform.toEntity.apply(Mockito.anyObject())).thenReturn(...);
}
}


When I RUN the JUNIT test, Mockito give me the error :


java.lang.NullPointerException
org.mockito.exceptions.misusing.InvalidUseOfMatchersException:
Misplaced argument matcher detected here:

-> at com.example.MyTest.setUp(MyTest.java:38)

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.


Do you have suggestions?

Answer

You're using public fields, which is not a good idea. But anyway, what you want to mock is the function, not the instance of MyEntityTransform. So you would need something like

@InjectMocks
private MyService _classUnderTest;

@Mock // or @Spy
private MyEntityTransform myEntityTransform;

@Before
public void prepare() {
    myEntityTransform.toEntity = mock(Function.class);
}

But quite frankly, I wouldn't use a public field of type Function. Instead, I would use a public method:

public class MyEntityTransform {
    public MyEntity toEntity(MyDTO record) {
        return new MyEntity();   
    }
}

Then you can mock MyEntityTransform and make its toEntity method return what you want. And if you need to pass a Function doing what the method does, use a method reference:

collection.stream().map(myEntityTranform::toEntity)