Java 如何为单元测试设计类
我有一个Java类,如下所示:Java 如何为单元测试设计类,java,unit-testing,Java,Unit Testing,我有一个Java类,如下所示: public class MyClass { /** Database Connection. */ private dbCon; public MyClass() { dbCon = ... } public void doSomethingWith(MyData data) { data = convertData(data); dbCon.storeData(dat
public class MyClass {
/** Database Connection. */
private dbCon;
public MyClass() {
dbCon = ...
}
public void doSomethingWith(MyData data) {
data = convertData(data);
dbCon.storeData(data);
}
private MyData convertData(MyData data) {
// Some complex logic...
return data;
}
}
因为这个类的真正逻辑在于convertData()
方法,所以我想为这个方法编写一个单元测试。
所以我读了这篇文章
很多人说测试私有方法的需要是一种设计的味道。如何才能做得更好
我看到两种方法:
convertData()
方法提取到某个实用程序类中。但我认为这也是一种不好的做法,因为这样的实用程序类将违反单一责任原则,除非我创建了很多可能只有一个或两个方法的实用程序类dbCon
,它允许我注入数据库连接的模拟版本,并针对publicdoSomething()
方法运行测试。这将是我首选的方法,但也有关于模拟的需要如何也是一种代码气味的讨论convertData
实现现在可以独立于MyClass
编写第二个构造函数,允许注入dbCon,这允许我注入数据库连接的模拟版本,并针对public doSomething()方法运行测试。这将是我首选的方法,但也有关于模拟的需要如何也是一种代码气味的讨论
又错了。研究了显式依赖原则
public class MyClass {
private DbConnection dbCon;
private MyDataConverter converter;
public MyClass(DbConnection dbCon, MyDataConverter converter) {
this.dbCon = dbCon;
this.converter = converter;
}
public void doSomethingWith(MyData data) {
data = converter.convertData(data);
dbCon.storeData(data);
}
}
MyClass
现在更诚实地说明了执行所需功能所需的内容
它还可以通过注入模拟依赖项进行单元测试
使用公共api将convertData()方法提取到某个实用程序类中。但我认为这也是一种不好的做法,因为这样的实用程序类将违反单一责任原则,除非我创建了很多可能只有一两个方法的实用程序类
你对这一点的解释是错误的。这正是SRP和SoC(关注点分离)的建议
convertData
实现现在可以独立于MyClass
编写第二个构造函数,允许注入dbCon,这允许我注入数据库连接的模拟版本,并针对public doSomething()方法运行测试。这将是我首选的方法,但也有关于模拟的需要如何也是一种代码气味的讨论
又错了。研究了显式依赖原则
public class MyClass {
private DbConnection dbCon;
private MyDataConverter converter;
public MyClass(DbConnection dbCon, MyDataConverter converter) {
this.dbCon = dbCon;
this.converter = converter;
}
public void doSomethingWith(MyData data) {
data = converter.convertData(data);
dbCon.storeData(data);
}
}
MyClass
现在更诚实地说明了执行所需功能所需的内容
它还可以与模拟依赖项的注入隔离进行单元测试。您需要注入
dbCon
并测试doSomethingWith
。“模拟的需要也是一种代码气味。”-如何、何处、谁?如果convertData
不依赖于MyClass
中的字段(即,是一个纯函数),那么将其设置为公共静态
IMHO是无害的。Java在某种程度上迫使您进入“一切都必须是对象”的思维模式,远离那些非常适合单元测试的功能原则。您需要注入dbCon
并测试doSomethingWith
。“模拟的需要也是一种代码气味。”-如何、何处、谁?如果convertData
不依赖于MyClass
中的字段(即,是一个纯函数),那么将其设置为公共静态
IMHO是无害的。Java在某种程度上迫使您进入“一切都必须是对象”的思维模式,远离那些非常适合单元测试的功能性原则。