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。
现在我有两种可能性如何做到这一点:
- 允许类SomeSpecialProcessing使用 setter 或构造函数在外部设置bufferedWriter,然后在单元测试中,我会将模拟传递到该字段。
- 在单元测试中,我将使用反射模拟bufferedWriter。
现在我更喜欢使用反射,但很多人说这是不好的做法,并建议将bufferedWriter添加到构造函数或设置器中。但是我认为仅仅因为单元测试而暴露类的内部字段是愚蠢的。
如何解决此类问题?
解决方案
但是我认为仅仅因为单元测试而暴露类的内部字段是愚蠢的
它不仅使您的代码更容易进行单元测试,而且总体上使您的代码更加灵活。
目前你有一个非常不灵活的课程。它可以进行一些处理并保存到一个名为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
? 哦,看,我已经打破了我的测试。
推荐阅读
- html - 用省略号截断字符串,但最后保留 img - 没有 JS
- c++ - TCPdump 在接收数据包时是否会剥离任何标头?
- python-3.x - 将 curl 命令转换为 Python3 requests.post (SOAP xml)
- javascript - Vue.js 在 for 循环中关闭表单标签
- angular - 在 RXJS 中找到合适的运算符来映射/减少 Observable 的内部条目
- javascript - import * as & import { default as } 的区别
- sas - 在 sas 比较中,仅输出差异和新记录
- python - Python Matplotlib:将轴设置为相对于一个值的增量
- java - 使用 PreBuiltTransportClient 调用 elasticsearch
- python - 用它们的计数替换嵌套列表中的元素