当你有零arg:constructors

时间:2015-06-05 21:23:22

标签: java unit-testing junit4 jmockit jmock

我正在尝试使用jmocks和junit编写单元测试。 (我的项目使用核心java-没有框架 - )当在一个no arg构造函数中初始化依赖项时,我无法通过模拟外部依赖项来为我的一些类编写单元测试。

由于我无法提供实际代码,试图通过示例解释该方案

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);


} }

此测试失败 - 模拟不起作用“未注入”,测试类与MalgovaApple一起执行......

现在,如果我们将下面的构造函数添加到VarietyChecker并使用它测试用例 - 它会给出预期的输出......

public VarietyChecker(Apple apple) {
    super();
    this.apple = apple;
}

并在单元测试中创建测试类对象     VarietyChecker打印机=新的VarietyChecker(mockapple);

仅仅为了测试目的而公开一个新的构造函数并不是一个好主意。毕竟据说你不应该单独改变测试代码,更重要的是,恐怕我们已经编写了“一些”(金额)代码......

我在junit或jmock中遗漏了一些东西,即使是非arg构造函数也可以使得模拟工作。或者这是简单的junit和jmocks的限制,我应该迁移到强大的东西,如 Jmockit / PowerMock

1 个答案:

答案 0 :(得分:2)

您应该考虑两种选择。

  1. 在描述时使用构造函数参数。

    在这种情况下,你不是“为了测试而暴露一个新的构造函数”。通过允许调用者使用不同的工厂实现,您可以使您的课程更加灵活。

  2. 不要嘲笑它。

    在这种情况下,您宣称使用其他工厂永远不会有意义。有时候这没关系。不过,那时问题就改变了。而不是,“我如何嘲笑这个?”你现在的问题是,“我从写这个测试中获得了什么?”你可能没有获得太多任何东西,根本不可能编写测试。

    如果你没有嘲笑并决定单元测试仍然值得,那么你应该在代码的其他方面断言。结束状态或某些输出。在这种情况下,工厂调用将成为不适合模拟的实现细节。

    重要的是不要陷入“单元测试一切”的心态。这是测试引起的设计损坏的一个方法。根据具体情况评估您的测试,确定他们是否为您提供任何实际价值。不写单元测试是一个有效的选项,有时甚至是合适的,即使你很难避免这样做。

  3. 在这种情况下,只有你能确定哪一个最有意义。从这个我们正在讨论的工厂对象的事实来看,我可能倾向于前者。