使用 JMock 在单元测试中不直接调用 Mock 方法
我有一个正在测试的方法。在其调用堆栈中,它调用一个 DAO,该 DAO 实习生使用 JDBC 与数据库聊天。我并不是很想知道 JDBC 层会发生什么;我只是想了解一下。我已经对此进行了测试,并且效果非常好。
我正在尝试使用 JMock、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 模拟间接对象。或者我没有看到关键点。我希望后半部分是真实的。
思考并感谢你。
I have a method under test. Within its call stack, it calls a DAO which intern uses JDBC to chat with the DB. I am not really interested in knowing what will happen at the JDBC layer; I already have tests for that, and they work wonderfully.
I am trying to mock, using JMock, the DAO layer, so I can focus on the details this method under test. Here is a basic representation of what I have.
@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.
}
It, from what I have learned creating this test, that I cannot mock indirect objects using JMock. OR I am not seeing a key point. I'm hoping for the second half to be true.
Thoughts and thank you.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
从代码片段中,我猜测 MyTestObject 使用反射、静态方法或字段来获取 DAO,因为它没有构造函数参数。 JMock 不会按类型替换对象(现在任何时候,都会有很多人推荐其他这样做的框架)。
这是故意的。 JMock 的目标是通过要求干净的依赖关系和集中的行为来突出对象设计的弱点。我发现将 DAO/JDBC 访问隐藏在域对象中最终会给我带来麻烦。这意味着域对象具有秘密依赖关系,这使得它们更难以理解和更改。我更喜欢在代码中明确这些关系。
因此,您必须以某种方式将模拟对象放入目标代码中。如果您不能或不想这样做,那么您将不得不使用另一个框架。
PS 就风格而言,您可以稍微简化此测试:
在测试中,您应该真正知道期望的值并将其输入到期望中。这使得更容易看到对象之间的值流。
From the snippet, I'm guessing that MyTestObject uses reflection, or a static method or field to get hold of the DAO, since it has no constructor parameters. JMock does not do replacement of objects by type (and any moment now, there'll be a bunch of people recommending other frameworks that do).
This is on purpose. A goal of JMock is to highlight object design weaknesses, by requiring clean dependencies and focussed behaviour. I find that burying DAO/JDBC access in the domain objects eventually gets me into trouble. It means that the domain objects have secret dependencies that make them harder to understand and change. I prefer to make those relationships explicit in the code.
So you have to get the mocked object somehow into the target code. If you can't or don't want to do that, then you'll have to use another framework.
P.S. One point of style, you can simplify this test a little:
within a test, you should really know what values to expect and feed that into the expectation. That makes it easier to see the flow of values between the objects.