美文网首页程序员
Spring boot 单元测试和集成测试

Spring boot 单元测试和集成测试

作者: Mason啊 | 来源:发表于2018-10-08 15:05 被阅读284次

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

    • 引入测试的jar
    <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>

    • Spring的测试
      一、测试service层,通过@Autowired注入相对应的bean即可。
    @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());
        }
    }
    
    • RequestBuilder/MockMvcRequestBuilders
      从名字可以看出,RequestBuilder用来构建请求的,其提供了一个方法buildRequest(ServletContext servletContext)用于构建MockHttpServletRequest;其主要有两个子类MockHttpServletRequestBuilder和MockMultipartHttpServletRequestBuilder(如文件上传使用),即用来Mock客户端请求需要的所有数据。
    • MockMvcRequestBuilders主要API

    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和MockMultipartHttpServletRequestBuilder API

    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):指定要上传的文件;

    • ResultActions

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

    • ResultMatcher/MockMvcResultMatchers

    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

    相关文章

      网友评论

        本文标题:Spring boot 单元测试和集成测试

        本文链接:https://www.haomeiwen.com/subject/yyvdaftx.html