无法模拟 Spring Data Jpa 的 void 方法

Unable to mock the void method of Spring Data Jpa

我在 void 方法下面,我想模拟它。

public void updateEmployee(EmployeeDto dto) {
    Employee d = convertToEntity(dto);
    employeeRepository.updateEmployee(d.getEmployeeName(), d.getEmployeeDescription(),
            d.getEmployeeOwnerEmployeeId(), d.getEmployeeCode(), d.getStatus());
}

但是我遇到了以下错误。

org.mockito.exceptions.misusing.NotAMockException: 
Argument passed to when() is not a mock!
Example of correct stubbing:
    doThrow(new RuntimeException()).when(mock).someMethod();
    at com.xxx.EmployeeServiceTest.test_UpdateEmployee(EmployeeServiceTest.java:120)
    at org.junit.internal.runners.TestMethod.invoke(TestMethod.java:68)
    at org.junit.internal.runners.MethodRoadie.run(MethodRoadie.java:89)
    at org.junit.internal.runners.MethodRoadie.runBeforesThenTestThenAfters(MethodRoadie.java:97)
    at org.junit.internal.runners.MethodRoadie.runTest(MethodRoadie.java:87)
    at org.junit.internal.runners.MethodRoadie.run(MethodRoadie.java:50)
    at org.junit.internal.runners.ClassRoadie.runUnprotected(ClassRoadie.java:34)
    at org.junit.internal.runners.ClassRoadie.runProtected(ClassRoadie.java:44)
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:86)
    at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:538)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:760)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:460)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:206)

测试方法

@RunWith(PowerMockRunner.class)
@PrepareForTest({StatusEnum.class})
public class EmployeeServiceTest {

    @Mock
    private Employee employeeMock;

    @InjectMocks
    private EmployeeServiceImpl employeeServiceImpl;

    @Mock
    private EmployeeRepository employeeRepositoryMock;

    @Mock
    private EmployeeDto employeeDtoMock;

    @Mock
    private StatusEnum statusEnum;

    @Mock
    private Exception ex;

    List<String> employeeNames = new ArrayList<>();

    @Before
    public void setup() {
        // To mock static methods or class
        mockStatic(StatusEnum.class);       
    }


    @Test
    public void test_UpdateEmployee() {
        doNothing().when(employeeServiceImpl).saveEmployee(any(EmployeeDto.class));
        employeeServiceImpl.updateEmployee(employeeDtoMock);

        /*doAnswer((i) -> {
            System.out.println("Employee setName Argument = " + i.getArgument(0));
            assertTrue("Pankaj".equals(i.getArgument(0)));
            return null;
        }).when(employeeServiceImpl).updateEmployee(employeeDtoMock);*/
    }
}

这里的异常对我来说似乎很清楚,employeeServiceImpl 似乎不是模拟。 你是如何实例化它的?在字段上使用 Mockito.mock@Mock ?

--- 编辑

为了澄清我的回答,在@Before(或你的测试中的等价物class)中用 mockito 实例化你的服务:

this.employeeService = Mockito.mock(EmployeeService.class);

@Mock
private EmployeeService employeeService;

然后它应该可以工作了。

--- 编辑 所以看到你如何注入你的模拟我想我可能会发生什么。 事实上 @InjectMocks 并不能使你的 EmployeeService a mock。它允许 mockito 知道让您的框架创建 bean 并注入您在其中创建的模拟。

在这里,如果您已将您的存储库声明为像这样的模拟

@Mock
private EmployeeRepository employeeRepository;

然后 EmployeeRepository 类型的 mock 将被注入到 employeeService 实例中,这不是 mock。

然后如果它实际上是你想要模拟的存储库,你应该把它放在你的测试中的 when 中,如:

    doNothing().when(employeeRepository).saveEmployee(any(EmployeeDto.class));
employeeServiceImpl.saveEmployee(employeeDtoMock);

然后调用您的服务将进入您的服务 saveEmployee 功能,但是当它到达模拟的存储库时,它将按预期工作。

如果它实际上是您想要模拟的整个服务,那么使用 @Mock 而不是 @InjectMocks 实例化它。