使用JMock在单元测试中不直接调用模拟方法

时间:2012-02-03 18:12:35

标签: junit jmock

我有一个正在测试的方法。在其调用堆栈中,它调用DAO,实习生使用JDBC与DB聊天。我真的不想知道在JDBC层会发生什么;我已经对此进行了测试,并且它们工作得非常好。

我正在尝试使用JOock模拟DAO层,因此我可以专注于此测试方法的细节。这是我所拥有的基本代表。

@Test    
public void myTest()
{
     context.checking(new Expectations() {
          {
               allowing(myDAO).getSet(with(any(Integer.class)));
               will(returnValue(new HashSet<String>()));
          }
     });

    // Used only to show the mock is working but not really part of this test.
    // These asserts pass.
    Set<String> temp = myDAO.getSet(Integer.valueOf(12));
    Assert.assertNotNull(temp);
    Assert.assertTrue(temp.isEmpty());

    MyTestObject underTest = new MyTestObject();
    // Deep in this call MyDAO is initialized and getSet() is called.
    // The mock is failing to return the Set as desired. getSet() is run as 
    // normal and throws a NPE since JDBC is not (intentionally) setup. I want 
    // getSet() to just return an empty set at this layer.
    underTest.thisTestMethod();
    ...
    // Other assertions that would be helpful for this test if mocking 
    // was working.
}

根据我学习创建此测试的内容,我无法使用JMock模拟间接对象。或者我没有看到关键点。我希望下半场是真的。

思考并感谢你。

1 个答案:

答案 0 :(得分:0)

从代码片段中,我猜测MyTestObject使用反射或静态方法或字段来获取DAO,因为它没有构造函数参数。 JMock没有按类型替换对象(现在任何时候,都会有很多人推荐其他框架)。

这是故意的。 JMock的目标是通过要求干净的依赖关系和集中行为来突出对象设计的弱点。我发现在域对象中隐藏DAO / JDBC访问最终会让我遇到麻烦。这意味着域对象具有秘密依赖关系,这使得它们更难理解和更改。我更喜欢在代码中明确表达这些关系。

所以你必须以某种方式将模拟对象放入目标代码中。如果您不能或不想这样做,那么您将不得不使用另一个框架。

P.S。一点风格,你可以稍微简化这个测试:

context.checking(new Expectations() {{
  allowing(myDAO).getSet(12); will(returnValue(new HashSet<String>()));
}});
在测试中,您应该真正知道期望的值,并将其提供给期望值。这样可以更容易地看到对象之间的值流。