java - 如何设计单元测试类

标签 java unit-testing

我有一个如下所示的 Java 类:

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() 方法,因此我想为此方法编写一个单元测试。 所以我读了这篇文章

How do I test a private function or a class that has private methods, fields or inner classes?

很多人说需要测试私有(private)方法是一种设计味道。怎样才能做得更好?

我看到两种方法:

  1. convertData() 方法提取到某个具有公共(public) API 的实用程序类中。但我认为这也是一种不好的做法,因为这样的实用程序类将违反单一责任原则,除非我创建大量的实用程序类,可能只有一两个方法。

  2. 编写第二个构造函数,允许注入(inject)dbCon,它允许我注入(inject)数据库连接的模拟版本并针对公共(public)doSomething() 方法。这将是我首选的方法,但也有关于模拟需求如何也是代码味道的讨论。

关于这个问题有什么最佳实践吗?

最佳答案

Extract the convertData() method into some utility class with a public api. But I think this would be also bad practice since such utility classes will violate the single responsibility principle, unless I create a lot of utility classes with maybe only one or two methods.

您对此的解释是错误的。这正是 SRP 和 SoC(关注点分离)所建议的内容

public interface MyDataConverter {
    MyData convertData(MyData data);
}

public class MyDataConverterImplementation implements MyDataConverter {
    public MyData convertData(MyData data) {
        // Some complex logic...
        return data;
    }
}

convertData 实现现在可以独立于 MyClass 进行独立测试

Write a second constructor that allows injection of the dbCon, which allows me to inject a mocked version of the database connection and run my test against the public doSomething() method. This would be my preferred approach, but there are also discussions about how the need of mocking is also a code smell.

又错了。研究显式依赖原则。

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 现在更加诚实地了解执行其所需功能所需的内容。

它还可以通过注入(inject)模拟依赖项来单独进行单元测试。

关于java - 如何设计单元测试类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49029540/

相关文章:

java - 截断所有表,清除一级和二级 hibernate 缓存的简单方法?

c# - 一个类中的测试是否保证不会同时执行?

c++ - 模拟系统调用 - 有更好的方法吗?

python - 调用 python Mock 时如何运行函数(以获得副作用)?

c# - 我如何测试是否已收到 MVVM 轻量级消息并对其采取行动?

java - ScheduledExecutorService每次循环后调用方法

java - cobertura 未能通过反射类测试

java - apache tomcat 启动失败,项目 lib 文件夹中出现 phoenix-5.0.0-HBase-2.0-client.jar

java - 将 24 位位图数据正确加载到 32 位位图对象中

java - hashCode() 没有 equals()?