无法模拟Spring Data Jpa的void方法

时间:2019-07-15 12:14:45

标签: java spring-data-jpa mockito powermock

我下面是想要模拟的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$2.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);*/
    }
}

1 个答案:

答案 0 :(得分:3)

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

---编辑

为阐明我的答案,请在@Before(或您的测试类中的等效项)中使用Mockito实例化您的服务:

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

@Mock
private EmployeeService employeeService;

然后它应该工作。

---编辑 因此,看看您如何注入模拟游戏,我想我可能会明白。 实际上,@InjectMocks不能成为您的EmployeeService a mock。它使Mockito知道让您的框架创建Bean并注入您在其中创建的模拟。

在这里,您是否已将存储库声明为此类

@Mock
private EmployeeRepository employeeRepository;

然后,类型为EmployeeRepository的模拟将被注入employeeService实例内部,而不是模拟。

然后,如果实际上它是您要模拟的存储库,则应将其放入测试中的when中,例如:

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

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

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

希望我的答案很清楚!