Java 无法模拟Spring数据Jpa的void方法

Java 无法模拟Spring数据Jpa的void方法,java,spring-data-jpa,mockito,powermock,Java,Spring Data Jpa,Mockito,Powermock,我有下面的无效方法,我期待得到嘲笑 public void updateEmployee(EmployeeDto dto) { Employee d = convertToEntity(dto); employeeRepository.updateEmployee(d.getEmployeeName(), d.getEmployeeDescription(), d.getEmployeeOwnerEmployeeId(), d.getEmployeeCod

我有下面的无效方法,我期待得到嘲笑

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);*/
    }
}
@RunWith(PowerMockRunner.class)
@PrepareForTest({StatusEnum.class})
公共类EmployeeServiceTest{
@嘲弄
私人雇员雇员模拟;
@注射模拟
私人雇员服务公司雇员服务公司;
@嘲弄
私人雇员安置雇员安置模拟;
@嘲弄
私人雇员对雇员的信任;
@嘲弄
私有StatusEnum StatusEnum;
@嘲弄
私人例外;
List employeeNames=new ArrayList();
@以前
公共作废设置(){
//模拟静态方法或类
mockStatic(StatusEnum.class);
}
@试验
公共无效测试_UpdateEmployee(){
doNothing().when(employeeServiceImpl).saveEmployee(any(EmployeeDto.class));
employeeServiceImpl.updateEmployee(employeeDtoMock);
/*拒绝((i)->{
System.out.println(“Employee setName Argument=“+i.getArgument(0));
assertTrue(“Pankaj”.equals(i.getArgument(0));
返回null;
}).when(employeeServiceImpl).updateEmployee(employeeDtoMock)*/
}
}

我很清楚这里的例外情况,
employeeServiceImpl
似乎不是一个模拟。 你是如何实例化它的?在字段上使用
Mockito.mock
@mock

---编辑

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

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

然后它就会起作用

---编辑 所以,看看你如何注射你的模拟,我想我可能知道发生了什么。 事实上,
@InjectMocks
并没有使您的
员工服务成为一个mock
。它允许mockito知道让您的框架创建bean并注入您在其中创建的mock

如果您已经像这样将存储库声明为一个模拟库,请参见此处

@Mock
private EmployeeRepository employeeRepository;
然后,类型为
EmployeeRepository
的模拟将被注入
employeeService
实例中,该实例不是模拟

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

    doNothing().when(employeeRepository).saveEmployee(any(EmployeeDto.class));
employeeServiceImpl.saveEmployee(employeeDtoMock);
然后调用您的服务将进入您的服务
saveEmployee
功能,但当它到达模拟存储库时,它将按预期工作


如果它实际上是您想要模拟的整个服务,那么使用
@mock
而不是
@injectmock

来实例化它。您如何创建
employeeServiceImpl
?此外,您还显示了
updateEmployee
的代码以及
saveEmployee
@SabirKhan的测试-我已经添加了
employeeServiceImpl
updateEmployee
代码已经显示。@PAA您使用的是哪种运行程序?@MadhuBhat-我使用的是
@RunWith(PowerMockRunner.class)@PrepareForTest({StatusEnum.class})
@PAA如果你是单元测试
updateEmployee
方法的
EmployeeServiceImpl
类,那么为什么你需要
doNothing().when(EmployeeServiceImpl.saveEmployee(any(EmployeeDto.class))
?@MihaiChelaru你确实是对的。我修改了我的答案来解释我的错误thoughts@PAA您使用的是
@InjectMocks
,它没有将
EmployeeService
声明为mock,而是将mock注入其中。我会把它写在我的答案里,这样我就有更多的空间写下来了@欢迎光临!很高兴我能帮忙!请毫不犹豫地将您的问题标记为已解决:)@PAA那么您想在这里测试什么?您想在调用
updateEmployee
它调用存储库时测试这一点吗?@ALeDref-我预先假设每个测试方法都应该有asserts语句,并希望使用void方法实现这一点。是的,虽然它是模拟的,但仍然调用存储库
    doNothing().when(employeeRepository).saveEmployee(any(EmployeeDto.class));
employeeServiceImpl.saveEmployee(employeeDtoMock);