首页 > 解决方案 > 无法模拟 Spring Data Jpa 的 void 方法

问题描述

我有下面的 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);*/
    }
}

标签: javaspring-data-jpamockitopowermock

解决方案


这里的例外对我来说似乎很清楚,employeeServiceImpl似乎不是一个模拟。你是如何实例化它的?使用Mockito.mock还是@Mock在现场?

- - 编辑

为了澄清我的答案,在@Before(或您的测试类中的等效项)使用 mockito 实例化您的服务:

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

或者

@Mock
private EmployeeService employeeService;

然后它应该工作。

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

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

@Mock
private EmployeeRepository employeeRepository;

然后EmployeeRepository将在employeeService实例内部注入一个类型的模拟,这不是模拟。

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

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

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

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


推荐阅读