0

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?

6
  • 2
    There is absolutely no reason to use mocking here. Mocking is used, when testing A, that uses B, to provide a fake B to A. Mocking what you're testing doesn't make sense. Commented Nov 18, 2016 at 20:36
  • I don't get it. If you want to test that Function why is Mockito involved? Commented Nov 18, 2016 at 20:36
  • I am sorry, I want to use the function toEntity as a mock in another test. Commented Nov 18, 2016 at 20:37
  • Post a complete minimal example reproducing the problem. Commented Nov 18, 2016 at 20:39
  • Your difficulty to mock the class is because you violate the most important principle in OOP information hiding. Method apply() (as you posted it here) is just a getter for the toEntity property. Either the class MyEntityTransform is a DTO without any logic, that this woule be OK but then it should not be mocked. Or MyEntityTransform contais some business logic, then nobody else should access its properties (directly). Commented Nov 18, 2016 at 20:49

1 Answer 1

8

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)
Sign up to request clarification or add additional context in comments.

1 Comment

Thank you! You helped me realize my mistake.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.