Junit4/Jmock2 缺乏支持基类
我们最终将单元测试代码库从 JUnit 3 迁移到 JUnit 4。我们还大量使用 JMock 2。
通过 JUnit 3,JMock 为您的测试提供了一个有用的基类 (MockObjectTestCase),它本身也是Junit TestCase 的子类,它处理有关模拟框架的各种内务管理职责。 这让测试班的生活变得非常轻松。
现在使用 JUnit4,JMock 不提供此类支持。 您的测试类必须手动创建一个 Mockery 对象,它必须记住使用正确的测试运行器注释,并且必须将所有与模拟相关的操作委托给模拟。 简而言之,它赋予测试类的责任远多于 JUnit 3 测试所需的责任。
现在我意识到 JUnit4 的魅力之一是不需要子类化某些东西,但这种 JMock 情况似乎是一种倒退,并且使得从 3 移植到 4 的工作比必要的要多。
我错过了什么吗? 实际上是否有一种很好的方法来编写我的 JUnit4/Jmock2 测试类,而无需手动将所有管道添加到每个类中? 当然,我可以编写自己的支持基类,但这似乎是 JMock2 API 中明显的遗漏,我不得不怀疑我是否错过了这一点。
编辑:这是可选支持类的源代码:
@RunWith(JMock.class)
public class JMockSupport {
protected final Mockery mockery = new Mockery();
protected void checking(ExpectationBuilder expectations) {
mockery.checking(expectations);
}
protected <T> T mock(Class<T> typeToMock) {
return mockery.mock(typeToMock);
}
protected <T> T mock(Class<T> typeToMock, String name) {
return mockery.mock(typeToMock, name);
}
protected Sequence sequence(String name) {
return mockery.sequence(name);
}
protected void setDefaultResultForType(Class<?> type, Object result) {
mockery.setDefaultResultForType(type, result);
}
protected void setImposteriser(Imposteriser imposteriser) {
mockery.setImposteriser(imposteriser);
}
protected void setNamingScheme(MockObjectNamingScheme namingScheme) {
mockery.setNamingScheme(namingScheme);
}
protected States states(String name) {
return mockery.states(name);
}
}
这包含 JUnit3 MockObjectTestCase 类定义的所有方法,这些方法只是回应嘲笑。 @RunWith 注释也在那里,以避免忘记将其添加到测试类中的可能性。
We're finally migrating our unit test code base from JUnit 3 to JUnit 4. We also make heavy use of JMock 2.
With JUnit 3, JMock provides a useful base class for your tests (MockObjectTestCase), which as well as itself being s subclass of Junit's TestCase, it handles various housekeeping duties regarding the mock framework. It makes life pretty easy for the test class.
Now with JUnit4, JMock provides no such support. Your test class has to manually create a Mockery object, it has to remember to use the correct test runner annotation, and must delegate all mock-related operations to the mockery. In short, it puts far more responsibility on the test class than was needed for JUnit 3 tests.
Now I appreciate that part of JUnit4's charm is there being no need to subclass something, but this JMock situation seems like a step backwards, and makes porting from 3 to 4 rather more work than should be necessary.
Am I missing something? Is there actually a nice way to write my JUnit4/Jmock2 test classes without manually adding all that plumbing to every class? I could write my own support base class, of course, but it seems such an obvious omission from the JMock2 API, I have to wonder if I've missed the point.
Edit: here's the source code of what the optional support class would look like:
@RunWith(JMock.class)
public class JMockSupport {
protected final Mockery mockery = new Mockery();
protected void checking(ExpectationBuilder expectations) {
mockery.checking(expectations);
}
protected <T> T mock(Class<T> typeToMock) {
return mockery.mock(typeToMock);
}
protected <T> T mock(Class<T> typeToMock, String name) {
return mockery.mock(typeToMock, name);
}
protected Sequence sequence(String name) {
return mockery.sequence(name);
}
protected void setDefaultResultForType(Class<?> type, Object result) {
mockery.setDefaultResultForType(type, result);
}
protected void setImposteriser(Imposteriser imposteriser) {
mockery.setImposteriser(imposteriser);
}
protected void setNamingScheme(MockObjectNamingScheme namingScheme) {
mockery.setNamingScheme(namingScheme);
}
protected States states(String name) {
return mockery.states(name);
}
}
This contains all of the methods that the JUnit3 MockObjectTestCase class defined, which just echo to the mockery. The @RunWith annotation is there also, to avoid the possibility of forgetting to add it to your test class.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
我也做过这样的迁移,这很痛苦。 我可以理解为什么他们对基类机制进行了分类——我试图将 JMock 基类与支持 Spring JUnit 的基类混合在一起,但这显然是行不通的。
一旦我开始这种迁移,我发现“优化”的一个领域是创建适当的 Expectation 基类,封装模拟对象上的常见操作,而不是为每个测试创建一个新的 Expectation 对象(和实例)。 这会让你少一点悲伤。
I've done this migration too, and it is a pain. I can understand why they've binned the base class mechanism - I was trying to juggle JMock base classes with Spring JUnit-enabled base classes, and that obvious doesn't work.
Once I embarked on this migration, one area I found for 'optimisation' was creating appropriate Expectation base classes encapsulating common operations on your mock objects, rather than creating a new Expectation object (and instance) for every test. That will save you a little grief.
拥有基类也存在问题。 在以前的版本中,我曾尝试组合来自不同测试框架的基类。 这就是为什么我们选择组合而不是继承。 看看我们可以用新的 @Rule 结构做什么将会很有趣。
There are also problems with having base classes. In previous versions, I suffered from trying to combine base classes from different test frameworks. That's why we went to composition over inheritance. It'll be interesting to see what we can do with the new @Rule structure.
不,没有这样的支持。
JMock 1 中的测试基类引起了很多问题,因为您只能扩展单个类,因此人们无法将 JMock 与也定义了基类的其他测试框架一起使用。 这就是为什么我们在 JMock2 中采用委托而不是继承。
也就是说,只要您使用 @RunWith(JMock.class) 注释您的类,您就可以使用 JMock2 的 JUnit3 支持库中的 MockObjectTestCase 类。 但我没试过。
有人请求“自动模拟”JUnit4 运行程序,它将通过自动反射为您创建上下文和模拟对象。 有些人喜欢这样,有些人则非常不喜欢。 如果您想要此功能,请在 JMock JIRA 中为该问题投票。
No. There is no such support.
The test base class in JMock 1 caused a lot of problems, because you can only extend a single class, and so people couldn't use JMock with other test frameworks that also defined base classes. That's why we went with delegation rather than inheritance in JMock2.
That said, you might be able to use the MockObjectTestCase class from JMock2's JUnit3 support library as long as you annotate your class with @RunWith(JMock.class). But I haven't tried.
There has been a request for an "auto-mocking" JUnit4 runner that will create the context and mock objects for you by automagical reflection. Some people like this, others really don't like it. If you want this feature, vote for the issue in the JMock JIRA.