4 回答
TA贡献1866条经验 获得超5个赞
您在这里遇到的问题是您的类与其他类的特定实现紧密耦合,因此您的“单元”被迫一起测试所有这些类的行为。
避免这种情况的典型方法是使用依赖注入,使您的类与接口而不是特定类耦合。然后您可以模拟注入的接口以对单个类的行为进行单元测试。
public class AImpl {
public B b;
public AImpl(B b) {
this.b = b;
}
}
public interface B {
// methods
}
public class BImpl implements B {
public C c;
public BImpl (C c) {
this.c = c;
}
}
当您创建AImpl生产代码时,您现在必须为其提供特定的C实现。您可以这样做new AImpl(new BImpl(new CImpl)),也可以使用像 Spring 这样的依赖注入框架来为您计算出所有这些细节。
B当您进行单元测试时,您可以创建一个模拟或存根以具有您希望为该特定测试展示的行为,并将该存根传递给构造函数: new AImpl(myMockedB)。
TA贡献1859条经验 获得超6个赞
B
您不应该在类中创建实例A
- 相反,您应该B
在创建时提供实例A
- 它称为Inversion of Control。流行的方法是使用依赖注入,例如使用 Spring 框架。
然后一切都变得简单 - 当您的类需要读取带有类的文件时FileReader
,为了测试您可以创建一个“假”实现,例如当您调用时FileReader.readFile()
,您的假实现将简单地返回硬编码字符串或流,具体取决于您想要什么。
这个概念真的很大,想象一下当你FileReader
实际上是一个DatabaseReader
or ExternalServiceCaller
。不是在单元测试中测试真实的数据库(祝你好运),而是创建一个FakeDatabaseReader
在常规 Java 上运行的数据库HashMap
,一切都很容易测试。
或者当您的代码处理时间/日期时,想象一个功能只在29th February
- 您可以等待 4 年来测试它,或者为Clock
您的测试提供一个设置为特定日期的对象。该类Clock
具有提供各种替代时钟的静态方法,以提供固定时刻、调整到未来或过去的时刻,或具有改变节奏的时钟。
TA贡献1816条经验 获得超6个赞
首先,由于您不能注入 B 类,因此所有此类都不是为了进行温和测试而设计的,请注意,由于您将任何新内容添加到类中,这与对实例进行硬编码非常相似。
适当的方式应该是
public class A {
public B b;
public A(B b) {
this.b = b;
}
}
请注意,您可以通过这种方式实例化类
A a = new A(b);
这样,b 可以是模拟或虚拟或存根或任何用于测试目的的对象。如果您面临遗留代码,您应该重构它以使其能够被测试。如果这是您的设计,您应该尽快重构以使其可测试。
控制反转和依赖注入应该有助于归档你想做的事情。
TA贡献1848条经验 获得超2个赞
不是我知道的,你会处理这些外部因素,或者在 A、B 或 C 类本身的开发过程中确保在测试过程中不会出现此类问题。
但是,如果您无法控制 A、B 或 C 类源,那么我认为您被卡住了!
添加回答
举报