写点什么

UT 之最后一测

用户头像
你呀不牛
关注
发布于: 2021 年 04 月 28 日
UT之最后一测


经过前面几次文章的分享的 UT 的相关知识,今天接着分享 UT 相关最后一测文章,希望对大家在 UT 的学习中有一点点的帮助。

Spring 集成测试

有时候我们需要在跑起来的 Spring 环境中验证,Spring 框架提供了一个专门的测试模块(spring-test),用于应用程序的集成测试。


在 Spring Boot 中,你可以通过 spring-boot-starter-test 启动器快速开启和使用它。


这时首先就有了 Spring 容器运行环境,就可以模拟浏览器调用等操作


引入测试坐标


<dependency>    <groupId>org.springframework.boot</groupId>    <artifactId>spring-boot-starter-test</artifactId>    <scope>test</scope></dependency><dependency>    <groupId>org.assertj</groupId>    <artifactId>assertj-core</artifactId>    <version>3.19.0</version>    <scope>test</scope></dependency>
复制代码


为了与生产环境配置区分开


新建一个 application-test.yml


server:  port: 8088 spring:  application:    name: hello-service-for-test
复制代码


controller 类,也就是被测对象


@RestControllerpublic class HelloController {
@RequestMapping(value = "/hello", method = RequestMethod.GET) public String hello() throws Exception { return "Hello World"; }}
复制代码

测试方案一

通过 TestRestTemplate 模拟调用 Rest 接口


@ExtendWith(SpringExtension.class)@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)@ActiveProfiles("test")class HelloControllerTest {
@Autowired private TestRestTemplate restTemplate;
@Value("${spring.application.name}") private String appName;
@BeforeEach void setUp() { assertThat(appName).isEqualTo("hello-service-for-test"); }
@Test void testHello() throws Exception { String response = restTemplate.getForObject("/hello", String.class);
assertThat(response).isEqualTo("Hello World"); }}
复制代码

测试方案二

通过 MockMvc 来调用 Rest 接口


@ExtendWith(SpringExtension.class)@SpringBootTest@AutoConfigureMockMvc@ActiveProfiles("test")class HelloControllerTest {
@Autowired private HelloController helloController;
@Autowired private MockMvc mockMvc;
@Value("${spring.application.name}") private String appName;
@BeforeEach void setUp() { assertThat(appName).isEqualTo("hello-service-for-test"); }
@Test void testHello() throws Exception { mockMvc.perform(MockMvcRequestBuilders.get("/hello")) .andDo(MockMvcResultHandlers.print()) .andExpect(MockMvcResultMatchers.status().isOk()) .andExpect(MockMvcResultMatchers.content().string("Hello World")); }}
复制代码


方案一会启动 Spring 容器,相对更符合我们测试思路,建议选用此方案测试


方案二不会启动内置的容器,所以耗时相对少一点


与 Spring 类似 dropwizard 也有一套测试方案,可以提供 Jetty 容器来做集成测试

Dropwizard 集成测试

引入 maven 坐标


<dependency>  <groupId>io.dropwizard</groupId>  <artifactId>dropwizard-testing</artifactId>  <version>2.0.21</version>  <scope>test</scope></dependency><dependency>  <groupId>org.junit.jupiter</groupId>  <artifactId>junit-jupiter</artifactId>  <version>5.6.2</version>  <scope>test</scope></dependency><dependency>  <groupId>org.assertj</groupId>  <artifactId>assertj-core</artifactId>  <version>3.19.0</version>  <scope>test</scope></dependency>
复制代码


被测试资源类


@Path("/ping")@Servicepublic class PingResource {    @GET    public String ping() {        return "pong";    }}
复制代码

测试方案一

不启动 Jetty 容器,通过 ResourceExtension 扩展测试


@ExtendWith(DropwizardExtensionsSupport.class)class PingResourceTest {
private static final ResourceExtension EXT = ResourceExtension.builder() .addResource(new PingResource()) .build();
@Test void should_get_pong_when_send_ping() { String response = EXT.target("/ping").request().get(String.class);
assertThat(response).isEqualTo("pong"); }}
复制代码

测试方案二

通过启动 Jetty 容器测试,为了避免项目中的循环依赖关系或加快测试运行速度,可以通过将 JAX-RS 资源编写为测试DropwizardClientExtension来测试 HTTP 客户端代码,并启动和停止包含测试的简单 Dropwizard 应用程序。


@ExtendWith(DropwizardExtensionsSupport.class)class PingResourceTest3 {
private static final DropwizardClientExtension EXT = new DropwizardClientExtension(new PingResource());
@Test void should_get_pong_when_send_ping() throws IOException { URL url = new URL(EXT.baseUri() + "/ping"); System.out.println(url.toString()); String response = new BufferedReader(new InputStreamReader(url.openStream())).readLine();
assertThat(response).isEqualTo("pong"); }}
复制代码

测试方案三

通过指定 yml 配置文件,Jersey HTTP client 调用 Rest 接口, 返回的客户端可以在测试之间重用


在 JUnit5 测试类中添加DropwizardExtensionsSupport注释和DropwizardAppExtension扩展名将在运行任何测试之前启动应用程序


并在测试完成后再次停止运行(大致等同于使用@BeforeAll@AfterAll


DropwizardAppExtension也暴露了应用程序的ConfigurationEnvironment并且应用程序对象本身,使这些可以通过测试进行查询。


新增配置文件\src\test\resources\hello.yml


server:  type: simple  rootPath: '/api/*'  applicationContextPath: /  connector:    type: http    port: 9090
复制代码


测试:


@ExtendWith(DropwizardExtensionsSupport.class)class PingResourceTest2 {
private static DropwizardAppExtension<HelloWorldServiceConfiguration> EXT = new DropwizardAppExtension<>( HelloWorldServiceApp.class, ResourceHelpers.resourceFilePath("hello.yml") );
@Test void should_get_pong_when_send_ping() { Client client = EXT.client(); String response = client.target( String.format("http://localhost:%d/api/ping", EXT.getLocalPort())) .request() .get(String.class);
assertThat(response).isEqualTo("pong"); }}
复制代码


参考

https://www.dropwizard.io/en/latest/manual/testing.html#

前文传送门

1、工作多年后我更了解了UT的重要性

2、五年了,你还在用junit4吗?

用户头像

你呀不牛

关注

公众号程序员牛不牛 2021.02.26 加入

你不牛,认识再多牛人也与你无关--公众号你呀不牛

评论

发布
暂无评论
UT之最后一测