Spring Boot可以和大部分流行的测试框架协同工作:通过Spring JUnit创建单元测试;生成测试数据初始化数据库用于测试;Spring Boot可以跟BDD(Behavier Driven Development)工具、Cucumber和Spock协同工作,对应用程序进行测试。
进行软件开发的时候,我们会写很多代码,不过,再过六个月(甚至一年以上)你知道自己的代码怎么运作么?通过测试(单元测试、集成测试、接口测试)可以保证系统的可维护性,当我们修改了某些代码时,通过回归测试可以检查是否引入了新的bug。总得来说,测试让系统不再是一个黑盒子,让开发人员确认系统可用。
在web应用程序中,对Controller层的测试一般有两种方法:(1)发送http请求;(2)模拟http请求对象。第一种方法需要配置回归环境,通过修改代码统计的策略来计算覆盖率;第二种方法是比较正规的思路,但是在我目前经历过的项目中用得不多,今天总结下如何用Mock对象测试Controller层的代码。
在之前的几篇文章中,我们都使用bookpub这个应用程序作为例子,今天也不例外,准备测试它提供的RESTful接口是否能返回正确的响应数据。这种测试不同于单元测试,需要为之初始化完整的应用程序上下文、所有的spring bean都织入以及数据库中需要有测试数据,一般来说这种测试称之为集成测试或者接口测试。
How Do
通过spirng.io新建的Spring Boot项目提供了一个空的测试文件——BookPubApplicationTest.java,内容是:
@RunWith(SpringJUnit4ClassRunner.class) @SpringApplicationConfiguration(classes = BookPubApplication.class) public class BookPubApplicationTests { @Test public void contextLoads() { } }
在pom文件中增加spring-boot-starter-test依赖,添加jsonPath依赖
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>com.jayway.jsonpath</groupId> <artifactId>json-path</artifactId> </dependency>
在BookPubApplicationTest中添加测试用例
package com.test.bookpub; import com.test.bookpub.domain.Book; import com.test.bookpub.repository.BookRepository; import org.junit.Before;import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.test.SpringApplicationConfiguration; import org.springframework.boot.test.TestRestTemplate; import org.springframework.boot.test.WebIntegrationTest; import org.springframework.http.MediaType; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.setup.MockMvcBuilders; import org.springframework.web.client.RestTemplate; import org.springframework.web.context.WebApplicationContext; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.hamcrest.Matchers.containsString; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; @RunWith(SpringJUnit4ClassRunner.class) @SpringApplicationConfiguration(classes = BookPubApplication.class) @WebIntegrationTest("server.port:0") public class BookPubApplicationTests { @Autowired private WebApplicationContext context; @Autowired private BookRepository bookRepository; @Value("${local.server.port}") private int port; private MockMvc mockMvc; private RestTemplate restTemplate = new TestRestTemplate(); @Before public void setupMockMvc() { mockMvc = MockMvcBuilders.webAppContextSetup(context).build(); } @Test public void contextLoads() { assertEquals(1, bookRepository.count()); } @Test public void webappBookIsbnApi() { Book book = restTemplate.getForObject("http://localhost:" + port +"/books/9876-5432-1111", Book.class); assertNotNull(book); assertEquals("中文测试", book.getPublisher().getName()); } @Test public void webappPublisherApi() throws Exception { //MockHttpServletRequestBuilder.accept方法是设置客户端可识别的内容类型 //MockHttpServletRequestBuilder.contentType,设置请求头中的Content-Type字段,表示请求体的内容类型 mockMvc.perform(get("/publishers/1") .accept(MediaType.APPLICATION_JSON_UTF8)) .andExpect(status().isOk()) .andExpect(content().string(containsString("中文测试"))) .andExpect(jsonPath("$.name").value("中文测试")); } }
分析
首先分析在BookPubApplicationTests类中用到的注解:
- @RunWith(SpringJUnit4ClassRunner.class),这是JUnit的注解,通过这个注解让SpringJUnit4ClassRunner这个类提供Spring测试上下文。
- @SpringApplicationConfiguration(classes = BookPubApplication.class),这是Spring Boot注解,为了进行集成测试,需要通过这个注解加载和配置Spring应用上下文。这是一个元注解(meta-annoation),它包含了@ContextConfiguration( loader = SpringApplicationContextLoader.class)这个注解,测试框架通过这个注解使用Spring Boot框架的SpringApplicationContextLoader加载器创建应用上下文。
- @WebIntegrationTest("server.port:0"),这个注解表示当前的测试是集成测试(integration test),因此需要初始化完整的上下文并启动应用程序。这个注解一般和@SpringApplicationConfiguration一起出现。server.port:0指的是让Spring Boot在随机端口上启动Tomcat服务,随后在测试中程序通过@Value("${local.server.port}")获得这个端口号,并赋值给port变量。当在Jenkins或其他持续集成服务器上运行测试程序时,这种随机获取端口的能力可以提供测试程序的并行性。
了解完测试类的注解,再看看测试类的内部。由于这是Spring Boot的测试,因此我们可通过@Autowired注解织入任何由Spring管理的对象,或者是通过@Value设置指定的环境变量的值。在现在这个测试类中,我们定义了WebApplicationContext和BookRepository对象。
每个测试用例用@Test注解修饰。在第一个测试用例——contextLoads()方法中,我仅仅需要确认BookRepository连接已经建立,并且数据库中已经包含了对应的测试数据。
第二个测试用例用来测试我们提供的RESTful URL——通过ISBN查询一本书,即“/books/{isbn}”。在这个测试用例中我们使用TestRestTemplate对象发起RESTful请求。
第三个测试用例中展示了如何通过MockMvc对象实现跟第二个测试类似的功能。Spring测试框架提供MockMvc对象,可以在不需要客户端-服务端请求的情况下进行MVC测试,完全在服务端这边就可以执行Controller的请求,跟启动了测试服务器一样。
测试开始之前需要建立测试环境,setup方法被@Before修饰。通过MockMvcBuilders工具,使用WebApplicationContext对象作为参数,创建一个MockMvc对象。
MockMvc对象提供一组工具函数用来执行assert判断,都是针对web请求的判断。这组工具的使用方式是函数的链式调用,允许程序员将多个测试用例链接在一起,并进行多个判断。在这个例子中我们用到下面的一些工具函数:
- perform(get(...))建立web请求。在我们的第三个用例中,通过MockMvcRequestBuilder执行GET请求。
- andExpect(...)可以在perform(...)函数调用后多次调用,表示对多个条件的判断,这个函数的参数类型是ResultMatcher接口,在MockMvcResultMatchers这这个类中提供了很多返回ResultMatcher接口的工具函数。这个函数使得可以检测同一个web请求的多个方面,包括HTTP响应状态码(response status),响应的内容类型(content type),会话中存放的值,检验重定向、model或者header的内容等等。这里需要通过第三方库json-path检测JSON格式的响应数据:检查json数据包含正确的元素类型和对应的值,例如jsonPath("$.name").value("中文测试")用于检查在根目录下有一个名为name的节点,并且该节点对应的值是“中文测试”。
一个字符乱码问题
-
问题描述:通过spring-boot-starter-data-rest建立的repository,取出的汉字是乱码。
-
分析:使用postman和httpie验证都没问题,说明是Mockmvc的测试用例写得不对,应该主动设置客户端如何解析HTTP响应,用get.accept方法设置客户端可识别的内容类型,修改后的测试用例如下:
@Test public void webappPublisherApi() throws Exception { //MockHttpServletRequestBuilder.accept方法是设置客户端可识别的内容类型 //MockHttpServletRequestBuilder.contentType,设置请求头中的Content-Type字段,表示请求体的内容类型 mockMvc.perform(get("/publishers/1") .accept(MediaType.APPLICATION_JSON_UTF8)) .andExpect(status().isOk()) .andExpect(content().string(containsString("中文测试"))) .andExpect(jsonPath("$.name").value("中文测试")); }
相关推荐
测试是保证软件质量的重要环节,书里会涵盖Spring Boot的单元测试和集成测试,使用Mockito和WireMock进行模拟测试,以及如何进行性能和压力测试。 最后,本书还会讲解Spring Boot的应用部署,包括本地开发环境的...
8. **测试与部署**: 开发过程中,单元测试和集成测试是必不可少的,Spring Boot支持JUnit和Mockito等测试工具。部署方面,Spring Boot应用可以被打包成可执行的JAR或WAR文件,部署在云服务器或本地服务器上。 9. **...
标题中的“Java毕业设计——基于spring boot的在线选房网站设计与实现”表明这是一个使用Java编程语言,并基于Spring Boot框架开发的毕业设计项目。Spring Boot是Spring生态中的一个核心组件,它简化了创建独立的、...
8. **Spring Boot测试**:讲解单元测试和集成测试的编写,包括Mockito和JUnit的使用。 9. **源码分析**:深入研究Spring Boot的部分源码,理解其设计模式和工作流程。 10. **开发工具**:如何在IDEA或Eclipse中...
本文通过一个具体的实战案例——构建一个基于React与Spring Boot的博客系统,深入讲解了前后端分离的设计思想和技术实践。 #### 项目概述 - **项目名称**:React-SpringBoot 博客系统 - **项目简介**:该系统旨在...
Spring Boot简化了Spring应用的初始搭建以及开发过程,通过内嵌式容器(如Tomcat)使得开发者无需额外配置即可运行应用程序。此外,它还提供了大量的起步依赖,使得添加如数据访问、安全、邮件服务等特性变得简单。...
在Spring Boot框架中,开发者可以创建自定义的`Starter`来简化项目配置,提高代码复用性。...理解和使用自定义Starter是提升Spring Boot项目开发效率的关键,它体现了Spring Boot的核心理念——"约定优于配置"。
5. **Spring Boot**:Spring4X中引入的Spring Boot简化了Spring应用的初始设置,通过自动配置和起步依赖,快速创建生产级别的应用。 6. **Spring Security**:提供了一套全面的安全管理框架,包括认证、授权、会话...
Spring提供了一个强大的Mock框架——Mockito,它可以生成Mock对象并设置预期行为。`@MockBean`是Spring Boot测试中与Mockito结合使用的注解,可以在测试环境中替换实际的bean。 此外,这个项目可能还包括了对Spring...
7. 自动化测试:Spring Boot支持JUnit和Mockito等单元测试框架,有助于进行自动化测试,确保代码质量。 8. 项目部署:Spring Boot应用打包成JAR或WAR文件后,可以通过Maven或Gradle进行部署,甚至可以打包成Docker...
5. **测试**:`spring-boot-starter-test`提供测试支持,包含JUnit、Mockito等工具,方便编写单元测试。 通过"TestProject"的实践,我们可以了解到Spring Boot如何快速构建一个具备基本功能的应用。从初始化项目到...
Spring Boot自带JUnit和Mockito等测试库,可以方便地编写测试用例,确保代码质量。 最后,系统的部署和运行也是关键环节。Spring Boot应用可以被打包为可执行的JAR或WAR文件,部署在各种服务器环境中,如Tomcat、...
10. **单元测试**:如何利用Spring Test和Mockito等工具对Spring应用进行单元测试。 11. **Spring Boot与Spring IoC**:Spring Boot简化了Spring应用的创建,但其底层依然基于Spring IoC,如何在Spring Boot中应用...
本教程旨在深入探讨Spring的核心概念和技术,通过提供的两份教程文档——"Learning Spring Application Development.pdf"和"Mockito for Spring.pdf",我们可以深入了解Spring的精髓。 "Learning Spring ...
你可以看到如何使用JUnit、Mockito等工具,结合Spring的@Test注解进行测试驱动开发。 最后,Spring Boot是近年来流行的Spring应用启动器,它简化了Spring应用的初始配置。在这个实例中,可能会有Spring Boot的主...
微服务测试设计和实践是构建云原生应用中不可或缺的一部分,尤其在采用Spring Boot和Kubernetes等技术栈的环境中。微服务架构将大型应用程序分解为小型、独立的服务,每个服务都可以独立开发、部署和扩展。这带来了...
Spring Boot支持JUnit和Mockito等测试工具,使得编写单元测试和集成测试变得简单。我们可以查看项目的src/test目录,了解测试的实现方式。 8. **Actuator** 对于生产环境,Spring Boot Actuator提供了监控和管理...
Spring Boot提供了丰富的测试工具,包括单元测试、集成测试和端到端测试。通过JUnit和Mockito等库,开发者可以对代码进行充分的测试,确保系统的稳定性。 综上所述,基于Spring Boot的高校竞赛管理系统充分利用了...
JUnit和Mockito是常用的Java测试框架,Spring Boot还提供了Spring Boot Test支持,方便对Spring应用进行测试。 总的来说,这个毕业设计项目涵盖了Java编程、Spring Boot框架的应用、数据库设计、前后端交互、游戏...
- `spring-boot-08-starter-test` 可能是关于自定义测试 starter 的内容,可能会介绍如何集成 JUnit、Mockito 等测试工具,并且定制测试环境。 - `spring-boot-08-starter` 可能是关于创建一个通用 starter 的步骤和...