我读的模拟示例越多,我就越困惑......
我有调用 FatDude 类 eatThemAll() 的 classA 方法 eat()
public class classA {
FatDude dude = new FatDude();
public String eat() {
String result = dude.eatThemAll();
}
}
public class FatDude {
public String eatThemAll() {
return "never full";
}
}
现在我想通过模拟 FatDude 类来测试 classA eat() 方法。
public class MockFatDude extends FatDude {
//override
public String eatThemAll() {
return "very full";
}
}
------------- test --------------
public class DoTest {
public void runTest() {
classA cl = new ClassA();
String out = cl.eat();
assertEqual(out, "very full");
}
}
这个 DoTest runTest() 当然不会使用 MockFatDude 类。我能想到的一种方法是更改代码以将 FatDude 传递给 ClassA 的 eat() 方法,例如:
public class classA {
public String eat(FatDude dude) {
String result = dude.eatThemAll();
}
}
然后把我的测试方法改成:
public class DoTest {
public void runTest() {
classA cl = new ClassA();
String out = cl.eat(new MockFatDude());
assertEqual(out, "very full");
}
}
但是如您所见,我不得不更改源代码以满足我的需要。 这是正确的做法吗?如果不允许我更改源代码怎么办? 我知道如果我应用 TDD 概念,可以更改源代码,但我想听听 如果我上面显示的是正确的方法,请提出一些意见或建议。
最佳答案
模拟和 Dependency Inversion Principle (DIP) 齐头并进,在大多数语言中,Mocks 通过接口(interface)解耦类来发挥最佳作用。
在你的例子中,这将在你不需要更改代码的情况下工作:(编辑:我的意思是,将来,如果你以这种方式设计你的应用程序,你将不需要更改代码来模拟依赖关系:))
- 抽象一个接口(interface) IDude
- 具体类 FatDude(和 MockFatDude)应该实现 IDude 接口(interface)
- 提供一个 IDude 实例被“设置”或注入(inject)到 classA 中的机制——依赖注入(inject)(构造函数或获取/设置);或服务定位器模式效果最好(替换具体的类工厂)
另请注意,许多模拟框架实际上允许您“即时”构建 Mock 具体类(参见 MoQ 等),因此您可以直接在单元测试中创建 MockFatDude 的功能。
关于java - 如何使用模拟对象编写单元测试?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4396113/