0

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

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

@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 模拟间接对象。或者我没有看到关键点。我希望下半场是真的。

想法和谢谢。

4

1 回答 1

0

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

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

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

PS 一点风格,可以稍微简化一下这个测试:

context.checking(new Expectations() {{
  allowing(myDAO).getSet(12); will(returnValue(new HashSet<String>()));
}});

在测试中,您应该真正知道期望的值并将其输入到期望中。这使得更容易看到对象之间的值流。

于 2012-02-07T09:27:58.157 回答