首页 > 解决方案 > 为什么嘲笑私有领域不好?

问题描述

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

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);
    }
}

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

现在我有两种可能性如何做到这一点:

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

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

如何解决此类问题?

标签: java

解决方案


但是我认为仅仅因为单元测试而暴露类的内部字段是愚蠢的

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

目前你有一个非常不灵活的课程。它可以进行一些处理并保存到一个名为something.log. 它以非常具体的方式(使用 a BufferedWriter)编写它,这可能是也可能不是编写该特定输出的最有效方式。基本上,您正在从班级的用户手中夺走控制权。

通过将您的依赖项推广到可以在某处写入字符串的任何内容,您可以增加类的灵活性并允许其用户自行决定提供哪些最佳依赖项以满足他们的要求。

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 个用例:写入实际日志,什么也不做。在某种程度上,您已经需要这种灵活性。您想通过使用反射来回避这一点,声称它同样好。

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


推荐阅读