【发布时间】:2021-11-05 14:48:54
【问题描述】:
我们的应用程序中有一段生产代码可以读取类似这样的原始数据库行:
List<Map<String, Object>> results =
txnNamedJdbcTemplate.queryForList(
transactionDbQueries.getProperty(QUERY_FETCH_REPORT_DETAILS).trim(), paramMap);
,然后它会执行大量的字段转换以生成所需结构的对象:
private Report extractReportData(long reportId, List<Map<String, Object>> results) {
Map<String, Object> reportRow = results.get(0);
Timestamp completeTs = (Timestamp) reportRow.getOrDefault(RS_PARAM_END_DATETIME, null);
Timestamp lastOpenedTs =
(Timestamp) reportRow.getOrDefault(RS_PARAM_LAST_OPENED_DATETIME, null);
String reportData =
reportRow.get(RS_PARAM_REPORT_DATA) == null
? StringUtils.EMPTY
: ((PGobject) reportRow.get(RS_PARAM_REPORT_DATA)).getValue();
Duration executionTime =
reportRow.containsKey(RS_PARAM_DURATION)
? Duration.ofSeconds(Long.parseLong(reportRow.get(RS_PARAM_DURATION).toString()))
: null;
String reportRunLevel = (String) reportRow.getOrDefault(RS_PARAM_ACCESS_LEVEL, null);
boolean reportOpened = (Boolean) reportRow.getOrDefault(RS_PARAM_OPENED_STATUS, Boolean.FALSE);
String reportCategory = (String) reportRow.getOrDefault(RS_PARAM_REPORT_CATEGORY, null);
Long scheduledId =
reportRow.get(RS_PARAM_SCHEDULED_ID) != null
? Long.parseLong(reportRow.get(RS_PARAM_SCHEDULED_ID).toString())
: null;
return Report.builder()
.reportId(reportId)
.reportName((String) reportRow.get(RS_PARAM_REPORT_NAME))
.reportType((String) reportRow.get(RS_PARAM_REPORT_TYPE))
.reportCategory(reportCategory)
.reportStatusDesc(
ReportStatus.values()[(Integer) reportRow.get(RS_PARAM_STATUS_ID) - 1].getDesc())
.submittedBy((String) reportRow.get(RS_PARAM_USER_NAME))
.submittedById((int) reportRow.get(RS_PARAM_USER_ID))
.submittedTime((Timestamp) reportRow.get(RS_PARAM_SUBMIT_DATETIME))
.completedTime(completeTs)
.lastOpeningTime(lastOpenedTs)
.reportData(reportData)
.reportRunLevel(reportRunLevel)
.opened(reportOpened)
.executionTime(executionTime)
.scheduledId(scheduledId)
.build();
}
我知道这不是最漂亮的代码,但那是遗留系统,而且离题了。
现在,我必须测试该代码以确保我们可以读取相同的对象并验证字段,所以我有以下 3 个场景:
-
在测试类中克隆此代码。我已经构建了一个测试实用程序来做到这一点。显然,这导致了相同的不漂亮代码的重复,这并不理想。
-
另一种方法是将此代码外包给某个实用程序类,让产品和测试代码都使用它,以避免重复。
-
此外,还有一种方法可以更改生产类的访问修饰符并进行测试。
这是一个使用适当数据库实例的集成测试,因此使用模拟是行不通的——我们需要读取实际数据。该示例实际上不是最好的,仅用于说明。主要问题:我们是在测试中重用生产代码还是最好复制它?
我强烈倾向于选项 #1,前提是如果我们在 prod 代码的转换中引入错误 - 我们如何检测它?为此,我认为代码隔离是最好的方法。
请问这背后有什么其他的意见或理由吗?
【问题讨论】:
-
我忘了说,这是一个使用适当数据库实例的集成测试,所以使用模拟是行不通的——我们需要读取实际数据。
-
所以,您是说您的选择是重用生产代码@bgore?
标签: java unit-testing testing