Spring Starter (XIV): two kinds of test methods Spring MVC Controller

As an R & D personnel, whether you are willing to test their own code, had to admit the importance of testing for the development of quality assurance, which is why each company's technical department are part of the reason for quality control needs, because the more the bug was found early, the lower the cost of code, for example, Dev environment bug found is lower than the cost of environmental QA, QA environment bug found is lower than the cost of Prod environment, environmental Prod find the most cost-bug, which is every most developers do not want to come across but can not afford to avoid reality forever.

Although it can not be completely avoided, but we can adequately test their own code, reduce the chance of the bug occurs.

So, this blog we mainly on three kinds of test methods under Spring MVC controller:

  1. After the deployment project test
  2. With JUnit testing framework and Spring Test
  3. With SwaggerUI interface documentation test

1. Deploy the project after the test

2 In the previous blog, we take is to test this way, the project will soon be labeled as war package, deployed to Tomcat, run the project, using tools such as browser or Postman testing controllers.

If you get a request, you can use the browser or Postman test.

If a post, put, delete and so on request, can be tested using the Postman.

Interested students can look at the previous two blog:

Spring Starter (XII): Spring MVC to use to explain

Spring Starter (xiii): Spring MVC commonly used to explain the comment

2. With Junit testing framework and Spring Test

Although the above methods can be tested, but each package, deploy, run the project, test, obviously inconvenient, but by providing a powerful Spring Spring Test framework for integration testing support, then we explain the specific use.

Spring because our project is managed by maven, so it's project directory structure has the following four:

  1. src / main / java: Item Code
  2. src / main / resources: Resources Project
  3. src / test / java: test code
  4. src / test / resources: test resources (the default directory is not generated, may need its own new)

In other words, we can put our test code under src / test / java directory, but until now, we did not add any test code in the directory.

2.1 Add dependence

Before adding test code, we need to add the following dependence in pom.xml:

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-test</artifactId>
    <version>4.3.18.RELEASE</version>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.12</version>
    <scope>test</scope>
</dependency>

Perhaps some students wonder, why add this dependency increases <scope>test</scope>, so what role does it?

With this question, we compiled under the project, was found on a normal compiled code compiler actually being given:

Error message prompts packages org.junit does not exist, but we obviously have added the dependent ah, this is why it will not, and <scope>test</scope>about what?

Congratulations, you guessed it, and indeed <scope>test</scope>relevant, if at this time you will remove the project is not being given the compiler ( but not recommended to be removed ).

This is because we added in the test code before, are placed under src / main / java directory, is now dependent package increased <scope>test</scope>, indicating that the survival period of these packages are in the test cycle, so we can test the code before the down into the src / test / java directory, as follows:

Build the project again, found by the compiler.

2.2 Adding a Controller

Before adding the controller, the new DemoService as follows:

package chapter05.service;

import org.springframework.stereotype.Service;

@Service
public class DemoService {
    public String saySomething() {
        return "hello";
    }
}

Note: This class adds @Service comment.

Then, the new controller NormalController, the method returns to its inside view jsp:

package chapter05.controller;

import chapter05.service.DemoService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class NormalController {
    @Autowired
    private DemoService demoService;

    @RequestMapping("/normal")
    public String testPage(Model model) {
        model.addAttribute("msg", demoService.saySomething());
        return "page";
    }
}

Then the new controller MyRestController, its inside method returns information:

package chapter05.controller;

import chapter05.service.DemoService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class MyRestController {
    @Autowired
    private DemoService demoService;

    @RequestMapping(value = "/testRest", produces = "text/plain;charset=UTF-8")
    public String testRest() {
        return demoService.saySomething();
    }
}

2.3 Adding test code

In src / test / java under the new package chapter05, then a new test class TestControllerIntegrationTests thereunder as follows:

package chapter05;

import chapter05.config.MyMvcConfig;
import chapter05.service.DemoService;
import org.junit.Before;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.context.WebApplicationContext;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = {MyMvcConfig.class})
@WebAppConfiguration("src/main/resources")
public class TestControllerIntegrationTests {
    private MockMvc mockMvc;

    @Autowired
    private DemoService demoService;

    @Autowired
    private WebApplicationContext webApplicationContext;

    @Before
    public void setup() {
        this.mockMvc = MockMvcBuilders.webAppContextSetup(this.webApplicationContext).build();
    }
}

Code to explain:

@RunWith(SpringJUnit4ClassRunner.class)Spring Test framework for providing functionality in JUnit environment.

@ContextConfiguration(classes = {MyMvcConfig.class})Used to load configuration ApplicationContext, wherein the attribute is used to load classes configuration class, MyMvcConfig configuration class code as follows:

package chapter05.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.view.InternalResourceViewResolver;
import org.springframework.web.servlet.view.JstlView;

/**
 * Spring MVC配置
 */
@Configuration
@EnableWebMvc
@ComponentScan("chapter05")
public class MyMvcConfig {
    /**
     * 视图解析器配置
     *
     * @return
     */
    @Bean
    public InternalResourceViewResolver viewResolver() {
        InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();

        viewResolver.setPrefix("/WEB-INF/classes/views/");
        viewResolver.setSuffix(".jsp");
        viewResolver.setViewClass(JstlView.class);

        return viewResolver;
    }
}

@WebAppConfiguration("src/main/resources") 用来声明加载的ApplicationContext是一个WebApplicationContext,它的属性指定的是Web资源的位置,默认为src/main/webapp,这里我们修改成

src/main/resources。

MockMvc用来模拟Mvc对象,它在添加了@Before注解的setup()中,通过this.mockMvc = MockMvcBuilders.webAppContextSetup(this.webApplicationContext).build();进行初始化赋值。

然后往测试类中添加如下测试代码:

@Test
public void testNormalController() throws Exception {
    mockMvc.perform(get("/normal"))
            .andExpect(status().isOk())
            .andExpect(view().name("page"))
            .andExpect(forwardedUrl("/WEB-INF/classes/views/page.jsp"))
            .andExpect(model().attribute("msg", demoService.saySomething()));
}

代码解释:

perform(get("/normal"))用来模拟向/normal发起get请求,

andExpect(status().isOk())预期返回的状态码为200,

andExpect(view().name("page"))预期视图的逻辑名称为page,

andExpect(forwardedUrl("/WEB-INF/classes/views/page.jsp"))预期视图的真正路径是/WEB-INF/classes/views/page.jsp",

andExpect(model().attribute("msg", demoService.saySomething()))预期Model里有一个msg属性,它的值是demoService.saySomething()的返回值hello。

执行该测试方法,测试通过:

最后往测试类中添加如下测试代码:

@Test
public void testRestController() throws Exception {
    mockMvc.perform(get("/testRest"))
            .andExpect(status().isOk())
            .andExpect(content().contentType("text/plain;charset=UTF-8"))
            .andExpect(content().string(demoService.saySomething()));
}

代码解释:

perform(get("/testRest"))用来模拟向/testRest发起get请求,

andExpect(status().isOk())预期返回的状态码为200,

andExpect(content().contentType("text/plain;charset=UTF-8"))预期返回值的媒体类型为text/plain;charset=UTF-8,

andExpect(content().string(demoService.saySomething()))预期返回值的内容为demoService.saySomething()的返回值hello。

执行该测试方法,测试通过:

3. 源码及参考

源码地址:https://github.com/zwwhnly/spring-action.git,欢迎下载。

Craig Walls 《Spring实战(第4版)》

汪云飞《Java EE开发的颠覆者:Spring Boot实战》

4. 最后

欢迎扫码关注微信公众号:「申城异乡人」,定期分享Java技术干货,让我们一起进步。

Guess you like

Origin www.cnblogs.com/zwwhnly/p/11592593.html