Java – How to JUNIT a java.util.Function using Mockito

javajunitmockito

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?

Best 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)