Junit Mockito:Mock一种操作输入参数的方法

Junit Mockito:Mock一种操作输入参数的方法,junit,mockito,Junit,Mockito,以前有人问过这个问题,但我看不到完全相同的问题&当然看不到解决方案 我试图模拟一个数据库Dao调用,该调用将对象保存到数据库中。 Dao调用返回新的PK,但也通过更新PK来修改传递的对象 我的测试正在按我想要的方式工作,除了验证失败,表明我没有通过预期的对象。然而,当我在调试器中暂停时,我可以看到insert确实在接受一个没有PK的对象。然后它正在修改它&调用的控制器可以看到更改的对象 @Test public void insertSampleAnalyteLabConfig() throws

以前有人问过这个问题,但我看不到完全相同的问题&当然看不到解决方案

我试图模拟一个数据库Dao调用,该调用将对象保存到数据库中。 Dao调用返回新的PK,但也通过更新PK来修改传递的对象

我的测试正在按我想要的方式工作,除了验证失败,表明我没有通过预期的对象。然而,当我在调试器中暂停时,我可以看到insert确实在接受一个没有PK的对象。然后它正在修改它&调用的控制器可以看到更改的对象

@Test
public void insertSampleAnalyteLabConfig() throws Exception {
    int newInt = 99;

    SampleAnalyteLabConfig sampleAnalyteLabConfig = createMockSampleAnalyteLabConfig(null);
    SampleAnalyteLabConfig sampleAnalyteLabConfig2 = createMockSampleAnalyteLabConfig(null);

    when(sampleAnalyteLabConfigService.save(sampleAnalyteLabConfig)).thenAnswer( invocation -> {
                SampleAnalyteLabConfig foo = (SampleAnalyteLabConfig) invocation.getArguments()[0];
                foo.setId(newInt);
                return new Long(newInt);
            }
    );

    mockMvc.perform(post("/api/lab/sampleanalytelab")
            .contentType(MediaType.APPLICATION_JSON_UTF8)
            .content(getBytes(sampleAnalyteLabConfig))).andExpect(status().isCreated());

    verify(sampleAnalyteLabConfigService, times(1)).save(sampleAnalyteLabConfig2);
}
测试输出如下:

参数不同!通缉: sampleAnalyteLabConfigService.save( SampleAnalyteLabConfig{{id=0}sampleId=2,analyteId=3,labId=1,numberOfRounds=null,AbsolutePerformanceCoreWarning=null} ); ->在com.foo.controllers.LabControllerTest.insertSampleAnalyteLabConfig(LabControllerTest.java:236)上 实际调用有不同的参数: sampleAnalyteLabConfigService.save( SampleAnalyteLabConfig{{id=99}sampleId=2,analyteId=3,labId=1,numberOfRounds=null,AbsolutePerformanceCoreWarning=null} ); ->位于com.foo.controllers.LabController.saveSampleAnalyteLabConfig(LabController.java:165)

比较失败:

参数不同!通缉: sampleAnalyteLabConfigService.save( SampleAnalyteLabConfig{{id=0}sampleId=2,analyteId=3,labId=1,numberOfRounds=null,AbsolutePerformanceCoreWarning=null} ); ->在com.foo.controllers.LabControllerTest.insertSampleAnalyteLabConfig(LabControllerTest.java:236)上 实际调用有不同的参数: sampleAnalyteLabConfigService.save( SampleAnalyteLabConfig{{id=99}sampleId=2,analyteId=3,labId=1,numberOfRounds=null,AbsolutePerformanceCoreWarning=null} ); ->位于com.foo.controllers.LabController.saveSampleAnalyteLabConfig(LabController.java:165)

已断开与目标VM的连接,地址:'127.0.0.1:61076',传输:'socket'


当您在或验证时将直接值传递给时,Mockito默认使用Java
equals
。您看到的是,您已经创建了两个独立的
SampleAnalyteLabConfig
实例,您正在用一个不同的实例(未修改)传入一个实例(该实例被修改以添加其ID)。假设
等于
hashCode
起作用,只需确保准备要验证的实例,以匹配要比较的修改实例即可

SampleAnalyteLabConfig sampleAnalyteLabConfig = createMockSampleAnalyteLabConfig(null);
SampleAnalyteLabConfig sampleAnalyteLabConfig2 = createMockSampleAnalyteLabConfig(null);

// ...
verify(sampleAnalyteLabConfigService, times(1)).save(sampleAnalyteLabConfig2);
参数不同!需要:sampleAnalyteLabConfigService.save(SampleAnalyteLabConfig{{id=0}sampleId=2,analyteId=3,labId=1,numberOfRounds=null,absolutePerformanceScoreWarning=null});->在com.foo.controllers.LabControllerTest.insertSampleAnalyteLabConfig(LabControllerTest.java:236)上

实际调用有不同的参数:sampleAnalyteLabConfigService.save(SampleAnalyteLabConfig{{id=99}sampleId=2,analyteId=3,labId=1,numberOfRounds=null,absolutePerformanceScoreWarning=null});->位于com.foo.controllers.LabController.saveSampleAnalyteLabConfig(LabController.java:165)


从评论中:

我知道我可以在sampleAnalyteLabConfig2上调用setId(),但这是我的问题,因为save()方法不是用Id集调用的,所以要求verify()确认它是用setId()调用的是错误的

Mockito不负责复制对象:当您使用
verify
检查对象时,您正在检查实例的当前状态,包括在调用服务期间或之后对其所做的任何修改。在考虑对象的三个实例时,记住这一点很重要:您的
sampleAnalyteLabConfig
、您的
sampleAnalyteLabConfig2
,以及ObjectMapper创建的然后传递到服务中的实例

您所做的验证语句将验证ObjectMapper创建的一个实例的post-
save
状态,包括您对
foo.setId(newInt)的调用从您的答案中。您没有根据调用期间创建的实例快照进行验证,因为Mockito没有创建快照


一般来说,我认为调用<代码> SETID(NeWTT)<代码>在您的代码> SAMPPLAYTALLATABACTION2中是安全的,并且对它进行测试,因为
newInt
是一个唯一的整数,除了您的测试之外,它不太可能来自任何地方:您可以从成功的验证中推断出对象被准确地传入和修改,并且只按照您的预期。我当然会这么做。但是,如果要检查传递到
save
的实例的修改前状态,则应删除修改状态的应答或将断言移动到应答中。(您也可以在更改答案中的状态之前克隆该实例,并测试克隆,但除了使用已编写的库或帮助程序在该状态下传递外,这没有多大价值。)

默认情况下,Mockito使用Java
equals
,当您将直接值传递到
验证时
。您看到的是,您已经创建了两个独立的
SampleAnalyteLabConfig
实例,您正在用一个不同的实例(未修改)传入一个实例(该实例被修改以添加其ID)。假设
等于
hashCode
起作用,只需确保准备要验证的实例,以匹配要比较的修改实例即可

SampleAnalyteLabConfig sampleAnalyteLabConfig = createMockSampleAnalyteLabConfig(null);
SampleAnalyteLabConfig sampleAnalyteLabConfig2 = createMockSampleAnalyteLabConfig(null);

// ...
verify(sampleAnalyteLabConfigService, times(1)).save(sampleAnalyteLabConfig2);
参数不同!需要:sampleAnalyteLabConfigService.save(SampleAnalyteLabConfig{{id=0}sampleId=2,analyteId=3,labId=1,numberOfRounds=null,absolutePerformanceScoreWarning=null});->在com.foo.controllers.LabControllerTest.insertSampleAnalyteLabConfig(La
@Test
public void insertSampleAnalyteLabConfig() throws Exception {
    int newInt = 99;

    SampleAnalyteLabConfig sampleAnalyteLabConfig = createMockSampleAnalyteLabConfig(null);

    when(sampleAnalyteLabConfigService.save(sampleAnalyteLabConfig)).thenAnswer( invocation -> {
        verify(sampleAnalyteLabConfigService, times(1)).save(sampleAnalyteLabConfig);
                SampleAnalyteLabConfig foo = (SampleAnalyteLabConfig) invocation.getArguments()[0];
                foo.setId(newInt);
                return new Long(newInt);
            }
    );

    mockMvc.perform(post("/api/lab/sampleanalytelab")
            .contentType(MediaType.APPLICATION_JSON_UTF8)
            .content(getBytes(sampleAnalyteLabConfig))).andExpect(status().isCreated());
}