gpt4 book ai didi

java - 解决 JUnit 中的重复测试习语

转载 作者:行者123 更新时间:2023-11-30 09:44:16 24 4
gpt4 key购买 nike

我有 2 个案例对我来说似乎是同一个问题,尽管它们是完全不同的情况:

1) 我正在测试对象对数据库的读写。因为我每次都在清理和重建对象,写入测试需要读取以确认每个字段的写入,而读取测试是先写入,所以测试最终看起来是一样的。然而,我不想让接口(interface)中的主要方法未经测试。

2) 在更小的情况下,我正在为一个小数据对象测试一个 copy() 方法和一个 equals() 方法。 copy() 方法使用 equals() 来测试自身,而 equals() 方法正在针对副本进行测试。同样,测试是重复的。

我觉得我在这里遗漏了一些东西,一些方法来分离依赖而不创建大量额外的工作(比如让原始 JDBC 写入数据库等)有没有一种标准的方法来处理这种情况重复测试?

最佳答案

对我来说,这种测试是一种代码味道。问题始终是:此测试究竟测试了什么?对于这个测试,您信任什么,不信任什么?

对我来说,你不能同时信任 read() 和 write(),它们可能在同一个类中,由同一个人编写。因此,如果您通过调用 write() 来测试 read(),那么这不是一个好的测试,您测试的是 write() 和 read() 是否同步,而不是它们做了它们应该做的事情。

在第二个示例中,您正在测试复制和等价是否同步,同样的问题。

假设这是持久层的实现:

public class PersistenceLayer {
private Object object;

void write(Object object) {
this.object = object;
}

Object read(Long id) {
return object;
}
}

问题是,你的测试会通过这个持久层吗?但它显然不会做你想要的。它不靠近数据库。同样,如果您的读写共享 session /事务,您的测试会通过吗?在这种情况下,数据可能永远不会真正提交给数据库。它可能会在最后进行回滚。但是您的测试仍然会通过。

阅读您的描述,您正在测试当我调用 write() 然后调用 read() 时,我得到一个类似的对象。我对 write() 方法的期望是它将数据写入数据库。所以如果我正在测试那个,我需要检查那个。所以我必须有另一个 channel 可以用来测试读写。这通常以通过 JDBC 创建新连接并进行选择结束。

所以我的测试代码是

testWrite() {
write(o);
Object o2 = readByJdbc("SELECT * FROM table WHERE id = ?", o);
assertObjectsEqual(o, o2); // this needs to compare all values
}

testRead() {
write(o);
Object o2 = read(o.id);
Object o3 = readByJdbc("SELECT * FROM table WHERE id = ?", o);

assertObjectsEqual(o2, o3); // this needs to compare all values
}

testWrite() 写入数据库并确保数据通过打开 JDBC 连接并以这种方式读取(不同的 session ,不同的事务,即数据将在数据库中)写入数据库。

testRead() 写入数据库并比较通过持久层和通过jdbc 读取返回的两个对象。我正在复制对 write(o) 的调用,但它是可以接受的,因为我们知道当另一个测试被调用时 write 是否会起作用。我可以再写一个 writeByJdbc,但我得到的只是一个测试会失败,而不是两个。

事实上,根据您的偏执程度,您不需要比较 assertObjectsEqual() 中的所有值。例如,如果您使用的是 hibernate,您可以假设所有内容都已正确声明,并测试数据库中是否存在该行。我经常这样做,因为我相信 hibernate 。但在那种情况下,我需要测试我如何调用 hibernate ,如何定义对象。

jdbc 代码不需要很长很复杂,对于一个简单的选择,我只是创建一个列到值的映射列表:

private List<Map<String, Object>> resultSetToListMap(ResultSet resultSet) throws SQLException {
int columnCount = resultSet.getMetaData().getColumnCount();
List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();

while (resultSet.next()) {
Map<String, Object> map = new LinkedHashMap<String, Object>();

for (int i = 1; i <= columnCount; i++) {
map.put(resultSet.getMetaData().getColumnName(i), resultSet.getObject(i));
}

list.add(map);
}

return list;
}

这对于大多数测试来说已经足够了。

关于java - 解决 JUnit 中的重复测试习语,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7988107/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com