java如何使用模拟对象编写单元测试?
我读的模拟例子越多,我就越困惑
我有一个类方法eat(),它调用FatDude类eatThemAll()
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类。我可以考虑的一种方法是更改代码,以传递ClassA的FatDude to 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概念,更改源代码是可以的,但我想听听 如果我上面所说的是正确的做法,我会给出一些意见或建议
# 1 楼答案
对。由于单元测试,您直接偶然发现了一些好的设计。如果你仔细观察,你会发现你移除了classA和FatDude之间的耦合。现在FatDude可以成为一个界面,在需要时传递行为。ClassA不需要知道它得到了什么样的胖子,也不需要知道如何构造一个胖子(带奶酪汉堡?)
你的解决方案正是我应该做的。只要您了解进行此类更改的原因和好处/缺点,就可以更改代码以适应TDD
# 2 楼答案
mock和Dependency Inversion Principle(DIP)齐头并进,在大多数语言中,mock通过接口将类解耦而工作得最好
在你的例子中,这将在你不需要更改代码的情况下工作:(编辑:我的意思是,在将来,如果你以这种方式设计你的应用程序,你将不需要将代码更改为模拟依赖项:))
还请注意,许多模拟框架实际上允许您“动态”构建模拟具体类(参见MoQ等人),因此您可以直接在单元测试中创建MockFatDude的功能