java - 一个模拟类工作正常,另一个返回 null
问题描述
我在我的一个单元测试中模拟 2 个类,用 Mockito 定义行为。何时调用函数。
其中一个模拟类完全按预期工作,另一个返回null
。我无法弄清楚两者之间有什么区别。
查询服务测试.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));
}
}
查询服务.java
@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);
}
}
QueryServiceTestConfig.java
@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()
返回了预期的结果,但hbaseConnectionService.getRowsByIDs()
模拟返回了null
。
elastic 和 hbase 连接服务类都定义在同一个文件夹中,它们唯一的注解是@Service
. 如果两者都失败,我会认为我配置了错误,但调用按预期工作的事实elasticConnectionService
告诉我正在发生其他事情。
解决方案
如果包JSONObject
is org.json
,JSONObject
的 equals 方法如下所示:
public boolean equals(Object object) {
return object == null || object == this;
}
由于 in 的实例与matchesArray
inQueryService
的实例不同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);
或者:
when(hbaseConnectionService.getRowsByIDs(Matchers.eq(matchesArray))).thenReturn(getRowsByIDs_result);
因为在引擎盖下,该Matchers.eq()
方法可能会调用JSONObject.equals()
,Matcher 可能无法工作(我没有检查源代码Matchers.eq()
)。
通常,在设置模拟方法调用时,您希望将您的方法包装parameter(s)
在 Mockito 的 Matcher 方法之一中。不幸的是,这在您的场景中不起作用。
(请注意,Mockito 类扩展了 Matchers)
推荐阅读
- ffmpeg - FFmpeg, av_frame_free - 不释放 av_frame_clone 分配的所有内存
- ruby-on-rails - 在创建和保存嵌套资源的实例时遇到问题
- arrays - 通用异步数组的 enumerate() 方法
- python-3.x - 从 OSX Automator 运行 python 3.5 脚本时报告实验室库不工作
- groovy - 如何在 Groovy 中跳过具有默认值的参数?
- django - 使用可调用作为 Django FilePathField 的路径属性?
- graphql - Apollo Server 2 中没有 CDN 的 GraphQL Playground
- spring - 基于 Spring 函数的注入
- ios - 添加分享按钮 - Swift
- javascript - getElementById 从祖先元素中删除子类