Stub private methods in class under test in junit 5, PowerMock not working with JUnit5

Viewed 2236

I want to stub a private method in the class under test. I am using junit 5. I have used before powermock to achieve this. Unfortunately junit 5 does not work with powermock.

I have simplified the example to better explain the problem. I have class that has has private helper method that is called inside public methods. Like below:

public class Service {
    private Repository repository;

    public Object findById(String id) {
        Object object = repository.findById(id);
        object = verify(object);
        return object;
    }

    private Object verify(Object object) {
        //removed for simplicity
        return object;
    }
}

Now I want to unit test the method findById of Service. I have used junit 5 with mockito to implement unit test for the Service class.

public class ServiceUTest {
    @InjectMocks
    private Service service;
    @Mock
    private Repository repository;

    @BeforeEach
    public void setUp() {
        MockitoAnnotations.initMocks(this);
    }

    @Test
    public void testFindById() {
        when(repository.findById(Mockito.any())).thenReturn(new Object());
        //how to stub verify method
    }
}

I would appreciate any help and guide to solve this problem.

Regards,

2 Answers

You can spy service and use PowerMockito to define the behavior for verify() method.

public class ServiceUTest {

    @InjectMocks
    private Service service;

    @Mock
    private Repository repository;

    @BeforeEach
    public void setUp() {
        MockitoAnnotations.initMocks(this);
    }

    @Test
    public void testFindById() {
        // Arrange
        Service spyService = spy(service);
        when(repository.findById(Mockito.any())).thenReturn(new Object());
        PowerMockito.when(spyService, "verify", any()).thenReturn(expectedObjectReturn);

        // Act
        Object actual = spyService.findById("id");

        // Assert
    }
}

Generally, a unit test is supposed to verify the public interface of a unit.

Stubbing private methods - is a bad idea. In this case, your tests are tightly coupled to the implementation details. And usually, you want to test the behavior but not implementation.

My suggestion is to return from repository such object which will comply with verification logic in a way you wanted to stub it.

Another approach to address such issues is to move out interesting bits into a new class. So then you can inject it as a dependency into your service. For example, you can use Specification pattern to extract verification logic.

Related