Java 一个模拟类工作正常,另一个返回null
我在一个单元测试中模拟了两个类,用Mockito定义了行为。然后调用函数 其中一个模拟类完全按照预期工作,另一个返回Java 一个模拟类工作正常,另一个返回null,java,spring,unit-testing,testing,mockito,Java,Spring,Unit Testing,Testing,Mockito,我在一个单元测试中模拟了两个类,用Mockito定义了行为。然后调用函数 其中一个模拟类完全按照预期工作,另一个返回null。我想不出两者之间有什么区别 QueryServiceTest.java @Import({ QueryServiceTestConfig.class }) @RunWith(SpringRunner.class) public class QueryServiceTest { @Autowired private QueryService querySe
null
。我想不出两者之间有什么区别
QueryServiceTest.java
@Import({ QueryServiceTestConfig.class })
@RunWith(SpringRunner.class)
public class QueryServiceTest {
@Autowired
private QueryService queryService;
@MockBean
private ElasticConnectionService elasticConnectionService;
@MockBean
private HBaseConnectionService hbaseConnectionService;
@Test
public void test_getRecordsFromQuery() throws IOException {
// creation of sample data for inputs and outputs goes here
// This mock works when called from queryService.getRecordsFromQuery()
when(elasticConnectionService.getRowIdsFromQuery(filterParams, testIndex)).thenReturn(getRowIdsFromQuery_result);
List<JSONObject> matches = queryService.getMatchingRowIds(getRowIdsFromQuery_result);
// matchesArray is directly defined to make sure its exactly the same as in queryService.getRecordsFromQuery()
JSONObject matchesArray = new JSONObject("{\"testTable\":[\"testUUID\"]}");
// This mock fails when called from queryService.getRecordsFromQuery()
when(hbaseConnectionService.getRowsByIDs(matchesArray)).thenReturn(getRowsByIDs_result);
// This returns getRowsByIDs_result as expected
JSONArray test = hbaseConnectionService.getRowsByIDs(matchesArray);
// This returns null
JSONArray actual = new JSONArray(queryService.getRecordsFromQuery(filterParams, testIndex));
}
}
@Service
public class QueryService {
@Autowired
private ElasticConnectionService elasticConnectionService;
@Autowired
private HBaseConnectionService hbaseConnectionService;
@Autowired
private PSQLConnectionService psqlConnectionService;
public String getRecordsFromQuery(
Map<String,String> filterParams,
String tablename) throws IOException {
/**
* Get records that match simple key/value filters
*/
// This mocked method returns exactly what was expected
List<List<JSONObject>> lookupsList = elasticConnectionService.getRowIdsFromQuery(filterParams, tablename);
List<JSONObject> matches = getMatchingRowIds(lookupsList);
// matchesArray is exactly the same as in the test class
JSONObject matchesArray = new JSONObject("{\"testTable\":[\"testUUID\"]}");
// This returns null
JSONArray hbResults = hbaseConnectionService.getRowsByIDs(matchesArray);
return hbResults.toString(4);
}
}
@Configuration
public class QueryServiceTestConfig {
@Bean
public QueryService queryService() {
return new QueryService();
}
@Bean
public ElasticConnectionService elasticConnectionService() {
return new ElasticConnectionService();
}
@Bean
public HBaseConnectionService hbaseConnectionService() {
return new HBaseConnectionService();
}
@Bean
public PSQLConnectionService psqlConnectionService() {
return new PSQLConnectionService();
}
}
最让我困惑的是,在queryService.getRecordsByQuery()
中,elasticConnectionService.getRowIDsFromQuery()
mock返回预期的结果,而hbasConnectionService.getRowsByIDs()
mock返回null
elastic和hbase连接服务类都在同一文件夹中定义,它们唯一的注释是
@service
。如果两者都失败了,我会认为我配置了错误的东西,但是elasticConnectionService
调用按预期工作的事实告诉我发生了其他事情。如果JSONObject
的包是org.json
,JSONObject
的equals方法如下所示:
public boolean equals(Object object) {
return object == null || object == this;
}
由于QueryService
中的matchesArray
实例与QueryServiceTest
中的实例不同,因此equals()
方法将返回false
尝试更改此选项:
when(hbaseConnectionService.getRowsByIDs(matchesArray)).thenReturn(getRowsByIDs_result);
查看您的结果是否发生变化:
when(hbaseConnectionService.getRowsByIDs(Mockito.any())).thenReturn(getRowsByIDs_result);
我认为你也可以做到这一点:
when(hbaseConnectionService.getRowsByIDs(Mockito.eq(matchesArray))).thenReturn(getRowsByIDs_result);
或:
因为在引擎盖下,Matchers.eq()
方法可能调用JSONObject.equals()
,所以匹配器可能无法工作(我没有检查Matchers.eq()
的源代码)
通常,在设置模拟方法调用时,您希望将参数
封装在一个Mockito的Matcher方法中。不幸的是,这在您的场景中不起作用
(注意Mockito类扩展了Matchers)JSONObject的包是什么?@stvnbrkdell我正在使用org.jsontanks!我可以使用
any()。在这种情况下,我可以不用使用any()
,但如果可能的话,我更愿意在测试中更加具体,有没有办法让JSONObject
在Mockito中按预期的方式运行?因为JSONObject的equals()方法是以这种方式实现的,不,你不能让它按你希望的方式运行(即,你不能使用匹配器)为了使代码更易于测试和更灵活,请考虑将MatChESART数组作为参数获取GETReCordSoFQuices()。这将允许您在单元测试中使用匹配器,也使您的方法更加灵活。好吧,在我开始挖掘新的JSON库之前,您是否推荐一个可以很好地与Mockito配合使用的库?请看Jackson
when(hbaseConnectionService.getRowsByIDs(Matchers.eq(matchesArray))).thenReturn(getRowsByIDs_result);