为什么嘲弄私人领域不好?

时间:2018-06-04 10:09:29

标签: java

假设我有一个类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. 允许使用setter或构造函数对 SomeSpecialProcessing 进行外部设置 bufferedWriter ,然后在单元测试中将mock传递给此字段。
  2. 在单元测试中,我将使用反射模拟 bufferedWriter
  3. 现在我更喜欢使用反射,但很多人说这是不好的做法,并建议将 bufferedWriter 添加到构造函数或setter中。但我认为仅仅因为单元测试而暴露类的内部字段是愚蠢的。

    如何解决这类问题?

1 个答案:

答案 0 :(得分:1)

  

但我觉得暴露内部课堂领域是愚蠢的   因为单元测试

这不仅使您的代码更容易进行单元测试,而且通常会使您的代码更加灵活。

目前你的课程非常灵活。它可以进行一些处理并持久保存到名为something.log的单个文件中。它以非常特定的方式(使用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?哦,看,我已经破坏了我的考试。