Что делает @Rule?
При попытке создать временный файл для модульных тестов я наткнулся на этот ответ, в котором упоминалось "TemporaryFolder JUnit @Rule" и ссылка, объясняющая, как его использовать. Что похоже на это:
@Rule
public TemporaryFolder testFolder = new TemporaryFolder();
а потом testFolder.newFile("file.txt")
У меня вопрос, что делает аннотация @Rule?
Удаление аннотации на самом деле ничего не меняет.
1 ответ
Как документация Rule
а также TemporaryFolder
утверждает, что он заботится о создании временного каталога перед каждым методом тестирования соответствующего класса и об удалении этой временной папки (и ее содержимого) после каждого метода тестирования.
Вы можете легко написать свои собственные правила, внедрив TestRule
или же MethodRule
или расширение от любого из его реализующих классов, таких как ExternalResource
,
Та же логика может быть гарантирована с @Before
а также @After
аннотированные методы инициализации и очистки. Однако вам нужно добавить логику прямо в тестовый класс. Если вам нужна логика в нескольких тестовых классах, вам нужно либо использовать наследование, написать несколько произвольных служебных классов или выполнить экстернализацию поведения. Правила делают именно последнее, позволяя вам повторно использовать этот тип логики инициализации или очистки и, кроме того, сокращать код и удалять ненужный код, чтобы сосредоточиться на реальном тесте, а не на конфигурации некоторых каталогов или серверов.
Этот проект, например, объявляет два типа серверов (Jetty или Tomcat), которые вы просто должны аннотировать @Rule
чтобы использовать сервер для интеграции или сквозных тестов.
Если вы хотите инициализировать правило только один раз для всех тестовых методов, просто замените @Rule
с @ClassRule
и инициализировать правило как public static
, Это инициализирует правило класса только один раз и будет повторно использоваться для каждого метода тестирования.
@ClassRule
public static JettyServerRule server = new JettyServerRule(new EmbeddedJetty());
@Test
public void myUnitTest() {
RestTemplate restTemplate = new RestTemplate();
String url = String.format("http://localhost:%s", server.getPort());
String response = restTemplate.getForObject(url, String.class);
assertEquals("Hello World", response);
}
В приведенном выше примере сервер Jetty инициализируется только один раз, и каждый метод тестирования класса тестирования может использовать этот сервер повторно, вместо того, чтобы запускать и разрушать новый сервер для каждого метода.
Несколько правил могут даже сочетаться с RuleChain
:
@Rule
public RuleChain chain= RuleChain.outerRule(new LoggingRule("outer rule")
.around(new LoggingRule("middle rule")
.around(new LoggingRule("inner rule");
В одном из наших интеграционных тестов, которые одновременно отправляли пару запросов в нашу службу JAX-RS, развернутую через Restlet на Jetty, мы получили следующие определения правил:
public static SpringContextRule springContextRule;
public static RestletServerRule restletServer;
static {
springContextRule = new SpringContextRule(JaxRsRestletTestSpringConfig.class);
restletServer = new RestletServerRule(springContextRule.getSpringContext());
}
@ClassRule
public static RuleChain ruleChain = RuleChain.outerRule(restletServer).around(springContextRule);
// Tempus Fugit rules
@Rule
public ConcurrentRule concurrently = new ConcurrentRule();
@Rule
public RepeatingRule repeatedly = new RepeatingRule();
Который инициализирует контекст аннотации Spring до запуска сервера Restlet/Jetty, чтобы включить внедрение bean-компонента Spring. Кроме того, правила Tempus Fugit используются для параллельного выполнения методов тестирования, чтобы раньше выявлять проблемы, связанные с условиями гонки и параллелизмом.