程序员

Spring boot 单元测试和集成测试

2018-10-08  本文已影响284人  Mason啊

测试是保证程序健壮的手段之一,也是非常重要的。今天我们来简单的聊聊Spring boot 如何进行测试。

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <scope>test</scope>
</dependency>

Spring boot 的测试只需要在测试类上加上@RunWith(SpringRunner.class),@SpringBootTest注解即可。SpringRunner.class 开启了Spring集成测试;@SpringBootTest 在没有配置上下文加载器的情况下默认使用了Spring boot的上下文加载器,当内部的配置没有使用,没有明确的字节码自动查找Spring boot配置,允许自定义属性,支持不同的web环境,在web服务器中测试下注册TestRestTemplate或者WebTestClient对象。准备工作完成之后就可以进行测试了。对于@SpringBootTest 注解可以看看官方的注释:

Annotation that can be specified on a test class that runs Spring Boot based tests.
Provides the following features over and above the regular <em>Spring TestContext
Framework</em>:
<ul>
<li>Uses {@link SpringBootContextLoader} as the default {@link ContextLoader} when no specific {@link ContextConfiguration#loader() @ContextConfiguration(loader=...)} is defined.</li>
<li>Automatically searches for a {@link SpringBootConfiguration @SpringBootConfiguration} when nested
{@code @Configuration} is not used, and no explicit {@link #classes() classes} are specified.</li>
<li>Allows custom {@link Environment} properties to be defined using the {@link #properties() properties attribute}.</li>
<li>Provides support for different {@link #webEnvironment() webEnvironment} modes,including the ability to start a fully running web server listening on a {@link WebEnvironment#DEFINED_PORT defined} or {@link WebEnvironment#RANDOM_PORT random} port.</li>
<li>Registers a {@link org.springframework.boot.test.web.client.TestRestTemplate
TestRestTemplate} and/or{@link org.springframework.test.web.reactive.server.WebTestClient WebTestClient} bean for use in web tests that are using a fully running web server.</li>
</ul>

@RunWith(SpringRunner.class)
@SpringBootTest
public class SpringBootApplicationTest {
    @Autowired
    private TestService testService;
    @Test
    public void test() {
      testService.test();
    }
}

二、Spring boot 进行web测试,Spring 3.2之后提供了mock mvc:能在一个近似真实的模拟Servlet容器里测试控制器,而不用实际启动应用服务器。接下来聊聊mock mvc是如何使用的。

可以使用MockMvcBuilders,该类提供了两个静态方法。

standaloneSetup():构建一个Mock MVC,提供一个或多个手工创建并配置的控制器。
webAppContextSetup():使用Spring应用程序上下文来构建Mock MVC,该上下文里可以包含一个或多个配置好的控制器。

二则的区别在于:

standaloneSetup()希望你手工初始化并注入你要测试的控制器,而webAppContextSetup()则基于一个webApplicationContext的实例,通常由Spring加载。前者同单元测试更加接近,你可能只想让它专注于单一控制器的测试,而后者让Spring加载控制器及其依赖,以便进行完整的集成测试。

控制器类

@RestController
@RequestMapping(value = "/my")
public class MyController {
  @RequestMapping(value = "/integration/{name}", method = RequestMethod.GET)
    public String integrationTest(@PathVariable String name) {
        return "name:" + name;
    }
}

测试类

@RunWith(SpringRunner.class)
@SpringBootTest
public class SpringBootApplicationTest {

    Logger logger = LoggerFactory.getLogger(SpringBootApplicationTest.class);

    @Autowired
    private WebApplicationContext context;
    private MockMvc mvc;

    @Before
    public void setupMockMvc() {
//     mvc = MockMvcBuilders.webAppContextSetup(context).build();
       mvc= MockMvcBuilders.standaloneSetup(new MyController()).build();
    }

    @Test
    public void getName() throws Exception {
        MockHttpServletRequestBuilder builder = MockMvcRequestBuilders.get("/my/integration/{name}", "lisi");
//        MockMvcRequestBuilders.post()
//        MockMvcRequestBuilders.delete()
//        MockMvcRequestBuilders.put()
//        ... 其他的http请求
        // 请求接受类型
//        builder.accept(MediaType.APPLICATION_JSON);
        // 参数
//        builder.param();
        // 请求的body
//        builder.content();
//        ... 还有一些其他的请求参数设置,具体的可以查看api

        // 打印并返回结果
        MvcResult result = mvc.perform(builder)
                // code 是否是200
                .andExpect(MockMvcResultMatchers.status().isOk())
                // 内容是不是 name:lisi
                .andExpect(MockMvcResultMatchers.content().string("name:lisi"))
                // 打印
                .andDo(MockMvcResultHandlers.print())
                // 返回结果
                .andReturn();
        MockHttpServletResponse response = result.getResponse();
        logger.info("响应状态:{},响应内容:{}", response.getStatus(), response.getContentAsString());
    }
}

MockHttpServletRequestBuilder get(String urlTemplate, Object... urlVariables):根据uri模板和uri变量值得到一个GET请求方式的MockHttpServletRequestBuilder;如get(/user/{id}, 1L);
MockHttpServletRequestBuilder post(String urlTemplate, Object... urlVariables):同get类似,但是是POST方法;
MockHttpServletRequestBuilder put(String urlTemplate, Object... urlVariables):同get类似,但是是PUT方法;
MockHttpServletRequestBuilder delete(String urlTemplate, Object... urlVariables) :同get类似,但是是DELETE方法;
MockHttpServletRequestBuilder options(String urlTemplate, Object... urlVariables):同get类似,但是是OPTIONS方法;
MockHttpServletRequestBuilder request(HttpMethod httpMethod, String urlTemplate, Object... urlVariables): 提供自己的Http请求方法及uri模板和uri变量,如上API都是委托给这个API;
MockMultipartHttpServletRequestBuilder fileUpload(String urlTemplate, Object... urlVariables):提供文件上传方式的请求,得到MockMultipartHttpServletRequestBuilder;
RequestBuilder asyncDispatch(final MvcResult mvcResult):创建一个从启动异步处理的请求的MvcResult进行异步分派的RequestBuilder;

MockHttpServletRequestBuilder header(String name, Object... values)/MockHttpServletRequestBuilder headers(HttpHeaders httpHeaders):添加头信息;
MockHttpServletRequestBuilder contentType(MediaType mediaType):指定请求的contentType头信息;
MockHttpServletRequestBuilder accept(MediaType... mediaTypes)/MockHttpServletRequestBuilder accept(String... mediaTypes):指定请求的Accept头信息;
MockHttpServletRequestBuilder content(byte[] content)/MockHttpServletRequestBuilder content(String content):指定请求Body体内容;
MockHttpServletRequestBuilder cookie(Cookie... cookies):指定请求的Cookie;
MockHttpServletRequestBuilder locale(Locale locale):指定请求的Locale;
MockHttpServletRequestBuilder characterEncoding(String encoding):指定请求字符编码;
MockHttpServletRequestBuilder requestAttr(String name, Object value) :设置请求属性数据;
MockHttpServletRequestBuilder sessionAttr(String name, Object value)/MockHttpServletRequestBuilder sessionAttrs(Map<string, object=""> sessionAttributes):设置请求session属性数据;
MockHttpServletRequestBuilder flashAttr(String name, Object value)/MockHttpServletRequestBuilder flashAttrs(Map<string, object=""> flashAttributes):指定请求的flash信息,比如重定向后的属性信息;
MockHttpServletRequestBuilder session(MockHttpSession session) :指定请求的Session;
MockHttpServletRequestBuilder principal(Principal principal) :指定请求的Principal;
MockHttpServletRequestBuilder contextPath(String contextPath) :指定请求的上下文路径,必须以“/”开头,且不能以“/”结尾;
MockHttpServletRequestBuilder pathInfo(String pathInfo) :请求的路径信息,必须以“/”开头;
MockHttpServletRequestBuilder secure(boolean secure):请求是否使用安全通道;
MockHttpServletRequestBuilder with(RequestPostProcessor postProcessor):请求的后处理器,用于自定义一些请求处理的扩展点;

MockMultipartHttpServletRequestBuilder继承自MockHttpServletRequestBuilder,又提供了如下API

MockMultipartHttpServletRequestBuilder file(String name, byte[] content)/MockMultipartHttpServletRequestBuilder file(MockMultipartFile file):指定要上传的文件;

调用MockMvc.perform(RequestBuilder requestBuilder)后将得到ResultActions,通过ResultActions完成如下三件事:
ResultActions andExpect(ResultMatcher matcher) :添加验证断言来判断执行请求后的结果是否是预期的;
ResultActions andDo(ResultHandler handler) :添加结果处理器,用于对验证成功后执行的动作,如输出下请求/结果信息用于调试;
MvcResult andReturn() :返回验证成功后的MvcResult;用于自定义验证/下一步的异步处理;

HandlerResultMatchers handler():请求的Handler验证器,比如验证处理器类型/方法名;此处的Handler其实就是处理请求的控制器;
RequestResultMatchers request():得到RequestResultMatchers验证器;
ModelResultMatchers model():得到模型验证器;
ViewResultMatchers view():得到视图验证器;
FlashAttributeResultMatchers flash():得到Flash属性验证;
StatusResultMatchers status():得到响应状态验证器;
HeaderResultMatchers header():得到响应Header验证器;
CookieResultMatchers cookie():得到响应Cookie验证器;
ContentResultMatchers content():得到响应内容验证器;
JsonPathResultMatchers jsonPath(String expression, Object ... args)/ResultMatcher jsonPath(String expression, Matcher matcher):得到Json表达式验证器;
XpathResultMatchers xpath(String expression, Object... args)/XpathResultMatchers xpath(String expression, Map<string, string=""> namespaces, Object... args):得到Xpath表达式验证器;
ResultMatcher forwardedUrl(final String expectedUrl):验证处理完请求后转发的url(绝对匹配);
ResultMatcher forwardedUrlPattern(final String urlPattern):验证处理完请求后转发的url(Ant风格模式匹配,@since spring4);
ResultMatcher redirectedUrl(final String expectedUrl):验证处理完请求后重定向的url(绝对匹配);
ResultMatcher redirectedUrlPattern(final String expectedUrl):验证处理完请求后重定向的url(Ant风格模式匹配,@since spring4);

今天先写到这,后续还会有补充,更加详细一点,然后还会有web安全测试,未完待续...若有什么问题或建议请联系,邮箱guofei_wu@163.com

参考文章:SpringMVC 测试 mockMVC

上一篇下一篇

猜你喜欢

热点阅读