java - 为什么 mock 私有(private)领域是不好的?

标签 java

假设我有一些 A 类,它内部依赖于 B 类,它在私有(private)字段中初始化:

class SomeSpecialProcessing {
    private BufferedWriter bufferedWriter;
    // some other fields

    public SomeSpecialProcessing() {
        this.bufferedWriter = new BufferedWriter(new FileWriter("something.log"));
    }

    public String doSomeProcessing() {
        // some special calculation 
        persistToDisc(somethingImportant);
        // some special processing
        return importantResult;
    }

    private void persistToDisc(String somethingImportant) {
        // this.bufferedWriter.write(str);
    }
}

现在我需要为公共(public)方法 doSomeProcessing() 创建单元测试,但我不想将任何内容写入光盘,因为这是一项耗时的操作。因此我必须模拟 bufferedWriter

现在我有两种可能性:

  1. 允许类 SomeSpecialProcessing 使用 setter 或构造函数在外部设置 bufferedWriter,然后在单元测试中我会将模拟传递到该字段。
  2. 在单元测试中,我将使用反射模拟bufferedWriter

现在我更喜欢使用反射,但很多人说这是不好的做法,并建议将bufferedWriter添加到构造函数或setter中。但我认为仅仅因为单元测试而暴露类的内部字段是愚蠢的。

如何解决此类问题?

最佳答案

But I think it's stupid to exposure internal fields of class just because of Unit tests

它不仅使您的代码更容易进行单元测试,而且总体上使您的代码更加灵活。

目前你的类(class)非常不灵活。它可以进行一些处理并保存到名为 something.log 的单个文件中。它以一种非常特定的方式(使用 BufferedWriter)写入它,这可能是也可能不是写入特定输出的最有效方式。基本上,您正在从类(class)用户手中夺取控制权。

通过将您的依赖项推广到任何可以在某处写入字符串的东西,您可以提高类的灵 active ,并允许其用户自己决定提供哪些最佳依赖项来满足他们的需求要求。

class SomeSpecialProcessing {
    private Writer writer;

    public SomeSpecialProcessing(Writer writer) {
        this.writer = writer;
    }

    public String doSomeProcessing() {
        // some special calculation 
        persist(somethingImportant);
        // some special processing
        return importantResult;
    }

    private void persist(String somethingImportant) {
        this.writer.write(str);
    }
}

您的类已经有 2 个用例:写入实际日志,而不执行任何操作。在某种程度上,您已经需要这种灵 active 。您想通过使用反射来回避这个问题,并声称它同样好。

问题是它并不那么好。基于反射的测试将变得更加脆弱。想重构私有(private)字段的名称吗?哦,看,我已经破坏了我的测试。想要更改内部实现以不使用 BufferedWriter 吗?哦,看,我已经破坏了我的测试。

关于java - 为什么 mock 私有(private)领域是不好的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50678127/

相关文章:

java - 在 Java 中提交 HTML 表单

java - AOP+同步

java - 无需下载即可获取文件的时间戳?

java - 使用纯Java通过JMeter执行JMS压力测试

java - 使用 JDBC 和 Kerberos 身份验证连接到 Hive 时出现异常

java - 域对象中的持久性注释是一种不好的做法吗?

java - 在 java 中使用 "final"关键字

java - 如何创建通过调用外部端点返回响应实体的端点

java - 缓存对象并在jsf中使用它们

java - Spring MVC HttpServletResponse 不覆盖 cookie