Spring 4.2附带了全新的JUnit规则: SpringClassRule
和SpringMethodRule
。 使用JUnit规则的主要优点是让开发人员摆脱SpringJUnit4ClassRunner
并在Spring集成测试中利用不同的JUnit运行器。 我认为Spring JUnit Rules的最大机会是易于创建参数化的集成测试。
要测试的代码
出于本文的目的,我使用了现有的Spring Boot Jersey Demo应用程序: https : //github.com/kolorobot/spring-boot-jersey-demo 。 该应用程序公开了简单的REST API以与客户对象一起使用。
集成测试–“旧”方式
在Spring 4.2之前,集成测试可能如下所示:
@RunWith(SpringJUnit4ClassRunner.class)
@ApplicationTest
public class SaveCustomerTest {private RestTemplate restTemplate = new TestRestTemplate("demo", "123");@Testpublic void savesCustomer() {// actURI uri = restTemplate.postForLocation("http://localhost:9000/customer",new Customer("John", "Doe"));// assertResponseEntity<Customer> responseEntity =restTemplate.getForEntity(uri, Customer.class);Customer customer = responseEntity.getBody();assertThat(customer.getFirstname()).isEqualTo("John");assertThat(customer.getLastname()).isEqualTo("Doe");}
}
@ApplicationTest
是一个分组注解,它包装了多个Spring的注解:
@Documented
@Inherited
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@SpringApplicationConfiguration(classes = Application.class)
@WebAppConfiguration
@org.springframework.boot.test.IntegrationTest("server.port=9000")
@ActiveProfiles("web")
@Sql(scripts = "classpath:data.sql", executionPhase = Sql.ExecutionPhase.BEFORE_TEST_METHOD)
public @interface ApplicationTest {}
您可能会注意到,以上测试使用标准SpringJUnit4ClassRunner
,这是一个自定义运行程序,在JUnit集成测试中增加了Spring Framework的支持。 并且由于不能在JUnit中使用多个运行程序,因此我们需要找到一种变通方法,以使用Spring和JUnitParams创建参数化测试(这并不是那么困难)。
使用Spring JUnit规则进行参数化测试
值得一提的是,Spring 4.2随附了SpringJUnit4ClassRunner
的便捷替代SpringJUnit4ClassRunner
:Spring JUnit Rules。 让我们来看一个例子:
@RunWith(JUnitParamsRunner.class)
@ApplicationTest
public class SaveCustomerParameterizedTest {@ClassRulepublic static final SpringClassRule SCR = new SpringClassRule();@Rulepublic final SpringMethodRule springMethodRule = new SpringMethodRule();private RestTemplate restTemplate = new TestRestTemplate("demo", "123");@Test@Parameterspublic void savesCustomer(String first, String last) {// actURI uri = restTemplate.postForLocation("http://localhost:9000/customer",new Customer(first, last));// assertResponseEntity<Customer> responseEntity =restTemplate.getForEntity(uri, Customer.class);Customer customer = responseEntity.getBody();assertThat(customer.getFirstname()).isEqualTo(first);assertThat(customer.getLastname()).isEqualTo(last);}public Object[] parametersForSavesCustomer() {return $($("John", "Doe"),$("John", "Smith"),$("Deborah", "Johnson"),$("Jan", "Kowalski"));}
}
原始代码没有太多更改,但最重要的是:
-
JUnitParamsRunner
– JUnitParams是标准JUnit参数化测试的替代方法。 我在这里写过博客: http : //blog.codeleak.pl/2013/12/parametrized-junit-tests-with.html和此处: http : //blog.codeleak.pl/2014/11/unit-testing- excercise-with-fizzbuzz.html 。 -
SpringClassRule
-支持的类级别功能SpringJUnit4ClassRunner
,必须用相结合SpringMethodRule
。 字段的名称无关紧要,但它必须是公共的,静态的和最终的。 -
SpringMethodRule
-支持的实例级和方法级设有SpringJUnit4ClassRunner
因此,它必须与组合SpringClassRule
-
@Parameters
–测试参数的注释。 默认情况下,需要parametersFor<methodName>
方法。
使用gradle test --tests *SaveCustomerParameterizedTest
运行测试将生成以下报告:
如您所见,执行了4个测试。 第一个花费了大部分时间,因为初始化了Spring上下文,后面的测试非常快。
摘要
在Spring Test Framework中添加Spring JUnit规则可以显着改善集成测试,尤其是在进行参数化测试时。 但是,不仅JUnitParams可以用于此目的。 您也可以尝试使用标准的JUnit org.junit.runners.Parameterized
。
资源资源
- Spring框架参考-http://docs.spring.io/spring/docs/current/spring-framework-reference/htmlsingle/#testcontext-junit4-rules
- 使用JUnitParams进行参数化的JUnit测试– http://blog.codeleak.pl/2013/12/parametrized-junit-tests-with.html
- JUnitParams – https://github.com/Pragmatists/JUnitParams
- 使用FizzBuzz和JUnitParams进行单元测试的练习– http://blog.codeleak.pl/2014/11/unit-testing-excercise-with-fizzbuzz.html
翻译自: https://www.javacodegeeks.com/2015/08/parameterized-integration-tests-with-spring-junit-rules.html