У меня возникли аналогичные проблемы, есть две работы вокруг. Мне не нравится ни один, но у них разные компромиссы:
1) Если ваше правило предоставляет методы очистки, вы можете вручную вызвать очистку внутри метода @Before
.
@ClassRule
public static MyService service = ... ;
@Before
public void cleanupBetweenTests(){
service.cleanUp();
}
Недостатком этого вам нужно помнить (и рассказать другим о вашей команде), чтобы всегда добавить, что метод @Before или создать абстрактный класс, тесты унаследовать от делать очистку для вас.
2) Имейте 2 поля, один статический, один нестатический, который указывает на один и тот же объект, каждое поле аннотируется либо @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, думая, что есть ошибка, так как одно и то же поле указывается дважды. Дополнительные усилия, комментарии кодов и т. Д. Не стоят того.
В то же время у вас все еще есть плита котла для копирования и вставки повсюду или абстрактных классов с использованием метода шаблона.
См. Также [JUnit issue # 793] (https://github.com/junit-team/junit/issues/793) на GitHub, где я задал этот же вопрос. – Rowan