我试图使用 jmocks 和 junit 编写单元测试。 (我的项目使用核心java-无框架-)当在无参数构造函数中初始化依赖项时,我无法通过模拟外部依赖项为我的某些类编写单元测试。
由于我无法提供实际的代码,尝试通过示例解释该场景
public interface Apple {
String variety();
}
实现。
public class MalgovaApple implements Apple {
@Override
public String variety() {
return "Malgova";
}
}
待测试类
public class VarietyChecker {
private Apple apple;
VarietyChecker(){
this.apple = new MalgovaApple();
// instead of new, a factory method is used in actual application
}
public String printAppleVariety(){
String variety = apple.variety();
if(variety.length() < 3){
System.out.println("Donot use Code names- Use complete names");
return "bad";
}
return "good";
}
}
使用 jmock 进行 Junit 测试
public class VarietyCheckerUnitTest{
Mockery context = new JUnit4Mockery();
@Before
public void setUp() throws Exception {
}
@After
public void tearDown() throws Exception {
}
@Test
public void test_VarietyChecker() throws Exception{
final Apple mockapple = context.mock(Apple.class);
VarietyChecker printer = new VarietyChecker();
context.checking(new Expectations(){{
oneOf(mockapple).variety();will(returnValue("as"));
}});
String varietyNameValid = printer.printAppleVariety();
assertEquals("bad",varietyNameValid);
} }
此测试失败 - 模拟不起作用,值“因为”未注入(inject),测试类使用 MalgovaApple 执行...
现在,如果我们将以下构造函数添加到 VarietyChecker 并使用它的测试用例 - 它会给出预期的输出...
public VarietyChecker(Apple apple) {
super();
this.apple = apple;
}
并在单元测试中创建测试类对象,例如 VarietyChecker 打印机 = new VarietyChecker(mockapple);
仅仅出于测试目的而公开新的构造函数并不是一个好主意。毕竟据说你不应该仅仅为了测试而改变代码,更重要的是,恐怕我们已经写了“一些”(数量)代码......
我是否在 junit 或 jmock 中缺少一些东西,即使在无参数构造函数的情况下也可以进行模拟工作。或者这是简单的 junit 和 jmocks 的限制,我应该迁移到像 Jmockit/PowerMock
这样强大的东西吗?最佳答案
您应该考虑两种选择。
按照您的描述使用构造函数参数。
在这种情况下,您并不是“仅出于测试目的而公开新的构造函数”。通过允许调用者使用不同的工厂实现,您可以使您的类更加灵活。
不要 mock 它。
在这种情况下,您声明使用不同的工厂是没有意义的。有时这没关系。但到那时,问题就发生了变化。而不是“我该如何 mock 这个?”现在你的问题是:“我从编写这个测试中得到什么?”您可能不会获得太多任何东西,并且编写测试可能根本没有多大意义。
如果您不模拟它并认为单元测试仍然值得,那么您应该对代码的其他方面进行断言。要么是最终状态,要么是某些输出。在这种情况下,工厂调用成为不适合模拟的实现细节。
重要的是不要陷入“单元测试一切”的心态。这是测试引起的设计损坏的一个原因。根据具体情况评估您的测试,确定它们是否为您提供任何真正的值(value)。不编写单元测试是一个有效的选择,有时甚至是合适的,即使这是您极力避免的选择。
只有您才能确定在这种情况下哪一个最有意义。由于我们正在讨论的是一个工厂对象,因此我可能倾向于前者。
关于java - 当参数为零时,如何通过模拟编写单元测试 :constructors,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30676048/