我遇到过类似的问题,有两种解决方法。我不喜欢任何一个,但它们有不同的权衡:
1)如果您的规则公开了清理方法,您可以在@Before
方法内手动调用清理。
@ClassRule
public static MyService service = ... ;
@Before
public void cleanupBetweenTests(){
service.cleanUp();
}
这样做的缺点是您需要记住(并告诉团队中的其他人)始终添加该 @Before 方法或创建一个您的测试继承的抽象类来为您进行清理。
2) 有 2 个字段,一个是静态的,一个是非静态的,它们指向同一个对象,每个字段分别由 a@ClassRule
或注释@Rule
。如果未公开清理,则需要这样做。当然,缺点是你还必须记住让@ClassRule 和@Rule 指向同一个看起来很奇怪的东西。
@ClassRule
public static MyService service = ... ;
@Rule
public MyService tmp = service ;
然后在您的实现中,您必须区分测试套件或单个测试。这可以通过检查是否Description
有任何孩子来完成。根据哪一个,您可以创建不同的Statement
适配器来处理清理或不处理:
@Override
protected void after() {
//class-level shut-down service
shutdownService();
}
@Override
protected void before() {
//class-level init service
initService();
}
@Override
public Statement apply(Statement base, Description description) {
if(description.getChildren().isEmpty()){
//test level perform cleanup
return new CleanUpStatement(this,base);
}
//suite level no-change
return super.apply(base, description);
}
这是Statement
每次测试之前要清理的自定义类:
private static final class CleanUpStatement extends Statement{
private final MyService service;
private final Statement statement;
CleanUpStatement(MyService service, Statement statement) {
this.service = service;
this.statement = statement;
}
@Override
public void evaluate() throws Throwable {
//clear messages first
myService.cleanUp();
//now evaluate wrapped statement
statement.evaluate();
}
}
毕竟,我会更倾向于选项 1,因为它更能揭示意图并且需要维护的代码更少。我也会担心其他人试图修改选项 2 中的代码,认为存在错误,因为同一个字段被指向两次。额外的努力、代码注释等是不值得的。
无论哪种方式,您仍然可以在任何地方复制和粘贴样板,或者使用模板方法抽象类。