栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

用Spring Boot和MockMVC测试进行进阶测试

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

用Spring Boot和MockMVC测试进行进阶测试

什么是Spring Boot测试框架?

构建在Spring测试框架之上

提供一组用于测试的注解和工具

@SpringBootTest        @MockBean       

@WebMvcTest        @WebFluxTest

@DataJpaTest        @DataJdbcTest        @JdbcTest        @DataMongoTest        @DataRedisTest

如何开始?添加Spring Boot测试的Starter

    org.springframework.boot
    spring-boot-starter-test
    test

使用spring-boot-starter-test的测试依赖项,其中包含

JUnit:默认版本是5(从Spring boot 2.2版本开始)

Spring Test和Spring Boot Test  测试注解

AssertJ: 一个断言库

Hamcrest:一个匹配库

Mockito:一个java模拟框架

JSONassert:一个用于JSON的断言库

JsonPath:用于JSON的XPath

使用@SpringBootTest进行集成测试

自动搜索@SpringBootConfiguration

  • 作为@ContextConfiguration的代替方案,用于创建测试使用的应用上下文
  • 使用@SpringBootTest进行集成测试,使用@ContextConfiguration进行分片测试

提供对不同webEnvironment模式的支持

        RANDOM_PORT,DEFINED_PORT,MOCK,NONE

由测试框架启动嵌入式服务器

        集成测试可以作为CI/CD管道的一部分来完成

自动配置一个TestRestTemplate

用@ExtendWith(从Spring Boot2.2开始)进行元注解

使用TestRestTemplate进行集成测试

方便的适宜用于集成测试的RestTemplate的代替品

  • 采取相对路径(而不是绝对路径)
  • 容错性:服务器应用程序收到404等错误响应时,他不会抛出一个异常
  • 配置为忽略cookies和重定向

如果你需要自定义

使用RestTemplateBuilder,例如添加自定义Message Converter

使用TestRestTemplate的示例代码
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)//知道与“随机”端口对话
public class AccountClientBootTests {
    @Autowired
    private TestRestTemplate restTemplate;//知道与“随机”端口对话
    // 测试代码
}
使用TestRestTemplate的示例代码 -- 测试代码
@Test
public void addAndDeleteBeneficiary() {
    //相对路径
    String addUrl = "/accounts/{accountId}/beneficiaries";
    URI newBeneficiaryLocation = restTemplate.postForLocation(addUrl, "David", 1);
    Beneficiary newBeneficiary= restTemplate.getForObject(
            newBeneficiaryLocation,Beneficiary.class);  
    assertThat(newBeneficiary.getName()).isEqualTo("David");
    restTemplate.delete(newBeneficiaryLocation);  
    ResponseEntity response= restTemplate.getForEntity(
            newBeneficiaryLocation, Account.class);
    //检查响应的状态码
    assertThat(response.getStatusCode()).isEqualTo(HttpStatus.NOT_FOUND);
}
对Spring MVC测试的需求

考虑到下面的控制器,你如何验证:

  • @PutMapping的结果是一个正确的URL映射?
  • @PathVariable的映射是有效的?
  • 帐户从传入的JSON/XML中被正确映射?
  • 返回的状态是HTTP 204?
  • 是否按照预期处理了任何异常?
@PutMapping("/account/{id}")
@ResponseStatus(HttpStatus.NO_CONTENT) // 204
public void updateOrder(@RequestBody Account account, @PathVariable long id) {
      // process updated account and return empty response  
      accountManager.update(id, account);
}
MVC测试框架概览

Spring框架的一部分

        在spring-test.jar中可以看到

目标:微测试Spring MVC代码提供一流的支持

通过DispatcherServlet处理请求

不需要运行web容器即可测试,不需要为测试代码协调服务器的URL/端口

示例:MockMvc 测试
//静态导入使得调用Builder和Matcher的静态方法更加容易。
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
//定义一个MockMVC环境(不过使@WebMvcTest会更简单)
@SpringBootTest(webEnvironment = WebEnvironment.MOCK)
@AutoConfigureMockMvc
public final class AccountControllerTests {
    @Autowired
    MockMvc mockMvc;
    @Test
    public void testBasicGet() { 
        //定义一个MockMVC环境(不过使@WebMvcTest会更简单)
        //对mockMvc实例进行测试
    	mockMvc.perform(get("/accounts")).andExpect(status().isOk());
    }
}
设置静态导入

静态导入是流体Builder的关键,MockMvcRequestBuilders.*和MockMvcResultMatchers.*

你可以在偏好设置中添加到Eclipse/STS的"favorite static menbers"中

  • java->Editor->Content Assist->Favorites
  • 添加到favorite static members
    • org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get
    • org.springframework.test.web.servlet.result.MockMvcResultMatchers.status
测试RESTful控制器

perform()的参数决定了动作

  • 来自MockMvcRequestBuilders的get()(或put(),post(),等等)
  • 用MockHttpServletRequestBuilders的方法进行追加
@Test
public void testRestfulGet() throws Exception {
    //MockMvcRequestBuilders的方法要放在perform()里面。
    mockMvc.perform(get("/accounts/{acctId}","123456001")
        .accept(MediaType.APPLICATION_JSON));
    …
    // Continued …
}
MockMvcRequestBuilders 静态方法

标准的HTTP get,put,post,delete操作

支持文件上传

参数是一个URI模版字符串

返回一个MockHttpServletRequestBuilder实例(用于连锁其他方法)

// 使用URI模版样式提交一个GET请求 
mockMvc.perform(get("/accounts/{acctId}", "123456001"))

// 使用请求参数样式提交一个GET请求  
mockMvc.perform(get("/accounts?myParam={acctId}", "123456001"))

方法

描述

param

添加一个请求参数,例如:param("myParam", 123)

requestAttr

添加一个对象作为请求的Attribute,另外,sessionAttr对Session作用域的对象做相同的处理

header

在请求中添加一个header的变量。另外,参考headers,它可以添加多个header

content

请求体

contentType

设置请求体的Content-Type(MIME类型)

accept

为预期的响应设置请求的类型(MIME类型)

locale

设定提出请求的地方

 测试RESTful控制器

perform()返回ResultActions对象

可以将expects链在一起,链式编程

来自MockMvcResultMatchers的content()和jsonPath();

@Test
public void testRestfulGet() throws Exception {  
    mockMvc.perform(
        get("/accounts/{acctId}","123456001")
        .accept(MediaType.APPLICATION_JSON))
        .andExpect(status().isOk())
        .andExpect(content().contentType("application/json"));
}

返回Matchers提供的指定的断言

方法

Matcher返回的

描述

content

ContentResultMatchers

与HTTP响应体有关的断言

header

HeaderResultMatchers

HTTP headers的断言

status

StatusResultMatchers

HTTP状态码的断言

xpath

使用Xpath表达式搜索返回的XML

jsonPath

使用JsonPath搜索返回的JSON

 MockHttpServletRequestBuilder示例

设置Accept Header

mockMvc.perform(get("/accounts/{acctId}","123456001")
     .accept("application/json")  // 请求JSON响应
...

//PUTting JSON payload

mockMvc.perform(put("/accounts/{acctId}","123456001")
    .content("{ ... ... }")
    .contentType("application/json")
...

打印调试信息

有时候你希望知道发生了什么

andDo()在MvcResult上执行动作

print()发送MvcResult到输出流,或者使用andReturn()以获取MvcResult对象

// 使用这个以访问print()方法
import static org.springframework.test.web.servlet.result.MockMvcResult.*;

// 还有其它静态导入
// 使用print()方法在测试中获取调试信息 
mockMvc.perform(get("/accounts/{acctId}", "123456001"))
        .andDo(print())	// 添加这一行将调试信息打印在控制台
        .andExpect(status().isOK())
        …
切片测试

什么是切片测试?

在应用程序的一个切片内执行独立的测试

        Web切片,储存库切片,缓存切片

各依赖项需要被模拟

使用@WebMvcTest进行切片测试
  • 禁用全部自动配置,只应用与MVC测试相关的配置
  • 自动配置Mvc测试框架        MockMvc bean是自动配置的,还有可选的Spring Security
  • 通常情况下,@WebMvcTest与@MockBean结合使用,模拟器依赖关系
//只创建与AccountController相关的bean
@WebMvcTest(AccountController.class)  
public class AccountControllerBootTests {

@Autowired
private MockMvc mockMvc;

@MockBean
private AccountManager accountManager;

@Test
public void testHandleDetailsRequest() throws Exception {
      // Test code
       }
}
@Test
public void testHandleDetailsRequest() throws Exception {

    // arrange
    given(accountManager.getAccount(0L))
    .willReturn(new Account("1234567890", "John Doe"));

    // act and assert
    mockMvc.perform(get("/accounts/0"))
    .andExpect(status().isOk())
    .andExpect(content().contentType(MediaType.APPLICATION_JSON)
    .andExpect(jsonPath("name").value("John Doe"))
    .andExpect(jsonPath("number").value("1234567890"));

    // verify
    verify(accountManager).getAccount(0L);
}
依赖的@Mock与@MockBean

@Mock:来自Mokito框架,当不需要Spring上下文时使用它

@MockBean 来自Spring Boot框架,当需要Spring上下文时使用它

当Spring上下文中不存在模拟bean时,创建一个新的模拟bean,或者当存在模拟Bean时明一个模拟Bean替换一个Bean

使用@DataJpaTest进行存储库切片测试
  • 可用于测试只关注JPA组件的情况下,加载@Repository beans,不包括其他@Components
  • 自动配置TestEntityManager
    • 用于JPA测试的EntityManager的代替品
    • 提供了EntityManager方法的一个子集
      • 只对测试有用的
      • 常见测试任务的辅助方法
      • persistFlushFind(),persistAndFlush()
  • 使用一个嵌入式内存数据库
    • 取代任何显示或自动配置的数据源
    • 可以使用@AutoConfigureTestDatabase注解来覆盖这些设置
总结

@SPringBootTest扩展了测试的选项

Spring MVC测试框架提供了一个模拟的Web环境,不需要运行外部的应用服务器

Boot提供了Web分片测试,Mock MVC测试专注于特定的控制器

Boot提供JPA分片测试

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/333238.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号