资讯详情

springboot单元测试

1.引入依赖

编写单元测试可以帮助开发人员编写高质量的代码,提高代码质量,减少Bug,便于重构。 Spring Boot在帮助我们测试应用程序时,提供了一些实用的程序和注释Spring Boot开启单元测试只需引入spring-boot-starter-test可以,它包含了一些主流的测试库。

引入spring-boot-starter-test:

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

运行Maven命令dependency:tree它包含以下依赖:

[INFO]  - org.springframework.boot:spring-boot-starter-test:jar:1.5.9.RELEASE:test [INFO] |   - org.springframework.boot:spring-boot-test:jar:1.5.9.RELEASE:test [INFO] |   - org.springframework.boot:spring-boot-test-autoconfigure:jar:1.5.9.RELEASE:test [INFO] |   - com.jayway.jsonpath:json-path:jar:2.2.0:test [INFO] |  |   - net.minidev:json-smart:jar:2.2.1:test [INFO] |  |  |  \- net.minidev:accessors-smart:jar:1.1:test [INFO] |  |  |     \- org.ow2.asm:asm:jar:5.0.3:test [INFO] |  |  \- org.slf4j:slf4j-api:jar:1.7.25:compile [INFO] |   - junit:junit:jar:4.12:test [INFO] |   - org.assertj:assertj-core:jar:2.6.0:test [INFO] |   - org.mockito:mockito-core:jar:1.10.19:test [INFO] |  |  \- org.objenesis:objenesis:jar:2.1:test [INFO] |   - org.hamcrest:hamcrest-core:jar:1.3:test [INFO] |   - org.hamcrest:hamcrest-library:jar:1.3:test [INFO] |   - org.skyscreamer:jsonassert:jar:1.4.0:test [INFO] |  |  \- com.vaadin.external.google:android-json:jar:0.0.20131108.vaadin1:test [INFO] |   - org.springframework:spring-core:jar:4.3.13.RELEASE:compile [INFO] |  \- org.springframework:spring-test:jar:4.3.13.RELEASE:test 
  • JUnit,单元测试的标准Java应用程序;
  • Spring Test & Spring Boot Test,对Spring Boot支持应用程序的单元测试;
  • Mockito, Java mocking任何模拟的框架Spring管理的Bean,例如,在单元测试中模拟第三方系统Service接口返回的数据不会真正调用第三方系统;
  • AssertJ,一个流畅的assertion库还提供了更多的期望值与测试返回值的比较方法;
  • Hamcrest,库的匹配对象(也称约束或谓词);
  • JsonPath,提供类似XPath获得这样的符号JSON数据片段;
  • JSONassert,对JSON对象或者JSON字符串断言库。

一个标准的Spring Boot测试单元应具有以下代码结构:

@DisplayName("AlarmMsgstationController测试类") @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) @AutoConfigureMockMvc @TestInstance(TestInstance.Lifecycle.PER_CLASS) @Transactional @TestMethodOrder(MethodOrderer.OrderAnnotation.class) public class AlarmMsgstationControllerTest { }  

2.JUnit4注解

JUnit4包含几个重要的注释:@BeforeClass、@AfterClass、@Before、@After和@Test。其中, @BeforeClass和@AfterClass在各类加载的开始和结束时开始和结束时运行;@Before和@After在每种测试方法开始和结束后运行。见如下例子:

@RunWith(SpringRunner.class) @SpringBootTest public class TestApplicationTests {      @BeforeClass     public static void beforeClassTest() {         System.out.println("before class test");     }          @Before     public void beforeTest() {         System.out.println("before test");     }          @Test     public void Test1() {         System.out.println("test 1 1=2");         Assert.assertEquals(2, 1   1);     }          @Test     public void Test2() {         System.out.println("test 2 2=4");         Assert.assertEquals(4, 2   2);     }          @After     public void afterTest() {         System.out.println("after test");     }          @AfterClass     public static void afterClassTest() {         System.out.println("after class test");     } } 
输出运行顺序 ... before class test before test test 1 1=2 after test before test test 2 2=4 after test after class test 

3、Assert断言 我们使用了上述代码Assert类提供的assert下面列出了一些常用的口法assert方法:

assertEquals("message",A,B),在比较两个对象时,判断A对象和B对象是否相等equals()方法。 assertSame("message",A,B),判断A对象是否与B对象相同,使用它==操作符。 assertTrue("message",A),判断A条件是否真实。 assertFalse("message",A),判断A条件是否不真实。 assertNotNull("message",A),判断A对象是否不为null。 assertArrayEquals("message",A,B),判断A数组是否等于B数组。 

4、MockMvc

MockMvc是服务端 Spring MVC测试支持的主入口点。

可用于模拟客户端请求进行测试MockMvc,字面上是指模拟MVC,也就是说,它可以模拟一个MVC环境,向Controller发送请求并得到响应。

在单元测试中使用MockMvc初始化如下:

@Autowired private MockMvc mockMvc;  @Autowired private WebApplicationContext wac;  @Before public void setupMockMvc(){     mockMvc = MockMvcBuilders.webAppContextSetup(wac).build(); }      

MockMvc模拟MVC请求

模拟一个get请求:

mockMvc.perform(MockMvcRequestBuilders.get("/hello?name={name}","mrbird")); 

模拟一个post请求:

mockMvc.perform(MockMvcRequestBuilders.post("user/{id}", 1));

模拟文件上传:

mockMvc.perform(MockMvcRequestBuilders.fileUpload("/fileupload").file("file", "文件内容".getBytes("utf-8")));

模拟请求参数:

// 模拟发送一个message参数,值为hello
mockMvc.perform(MockMvcRequestBuilders.get("/hello").param("message", "hello"));
// 模拟提交一个checkbox值,name为hobby,值为sleep和eat
mockMvc.perform(MockMvcRequestBuilders.get("/saveHobby").param("hobby", "sleep", "eat"));

也可以直接使用MultiValueMap构建参数:

MultiValueMap<String, String> params = new LinkedMultiValueMap<String, String>();
params.add("name", "mrbird");
params.add("hobby", "sleep");
params.add("hobby", "eat");
mockMvc.perform(MockMvcRequestBuilders.get("/hobby/save").params(params));

模拟发送JSON参数:

String jsonStr = "{\"username\":\"Dopa\",\"passwd\":\"ac3af72d9f95161a502fd326865c2f15\",\"status\":\"1\"}";
mockMvc.perform(MockMvcRequestBuilders.post("/user/save").content(jsonStr.getBytes()));

实际测试中,要手动编写这么长的JSON格式字符串很繁琐也很容易出错,可以借助Spring Boot自带的Jackson技术来序列化一个Java对象(可参考Spring Boot中的JSON技术),如下所示:

User user = new User();
user.setUsername("Dopa");
user.setPasswd("ac3af72d9f95161a502fd326865c2f15");
user.setStatus("1");

String userJson = mapper.writeValueAsString(user);
mockMvc.perform(MockMvcRequestBuilders.post("/user/save").content(userJson.getBytes()));

其中,mapper为com.fasterxml.jackson.databind.ObjectMapper对象。

模拟Session和Cookie:

mockMvc.perform(MockMvcRequestBuilders.get("/index").sessionAttr(name, value));
mockMvc.perform(MockMvcRequestBuilders.get("/index").cookie(new Cookie(name, value)));

设置请求的Content-Type:

mockMvc.perform(MockMvcRequestBuilders.get("/index").contentType(MediaType.APPLICATION_JSON_UTF8));

设置返回格式为JSON:

mockMvc.perform(MockMvcRequestBuilders.get("/user/{id}", 1).accept(MediaType.APPLICATION_JSON));

模拟HTTP请求头:

mockMvc.perform(MockMvcRequestBuilders.get("/user/{id}", 1).header(name, values));

MockMvc处理返回结果

期望成功调用,即HTTP Status为200:

mockMvc.perform(MockMvcRequestBuilders.get("/user/{id}", 1))
    .andExpect(MockMvcResultMatchers.status().isOk());

期望返回内容是application/json:

mockMvc.perform(MockMvcRequestBuilders.get("/user/{id}", 1))
    .andExpect(MockMvcResultMatchers.content().contentType(MediaType.APPLICATION_JSON));

完整示例

@DisplayName("AlarmMsgstationController测试类")
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@AutoConfigureMockMvc
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
@Transactional
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
public class AlarmMsgstationControllerTest {

    @Autowired
    private MockMvc mockMvc;

    @Autowired
    private ShiroController shiroController;

    private String token;

    private ListUserVO testUser;

    @BeforeAll
    void setUpAll() {
        // 以系统管理员身份登录系统
        LoginDTO loginDTO = new LoginDTO();
        loginDTO.setUserName("");
        loginDTO.setPassword("");
        。。。。。。。。。。。。。。。。。。。。。。。
    }

    @AfterAll
    void tearDownAll() {
        shiroController.logout(token);
    }

    @BeforeEach
    void setUp() {
        System.out.println("************************" + "函数测试开始" + "***************************");
    }

    @AfterEach
    void tearDown() {
        System.out.println("************************" + "函数测试结束" + "***************************");
    }

    @Test
    @DisplayName("获取告警方式列表测试")
    @Order(1)
    @Rollback(false)
    void listAlarmMsgstationTest() throws Exception {
        // 模拟用户数据
        MultiValueMap<String, String> params = new LinkedMultiValueMap<>();
        params.add("packageNum", Integer.toString(1));
        params.add("packageSize", Integer.toString(10));
        params.add("orderFields", "id");
        params.add("order", "desc");
        params.add("searchFields", "username");
        params.add("search", "hhhh");
        // 模拟请求
        String url = "/alarm/alarmMsgstations";
        RequestBuilder req = MockMvcRequestBuilders.get(url).header("token", token).header("timed_task", false)
                .contentType(MediaType.APPLICATION_JSON_UTF8).params(params);
        MvcResult result = mockMvc.perform(req).andReturn();
        // 获取请求结果
        result.getResponse().setCharacterEncoding("UTF-8");
        int httpStatus = result.getResponse().getStatus();
        String content = result.getResponse().getContentAsString();
        JSONObject jsonObject = JSON.parseObject(content);
        Integer resultCode = (Integer) jsonObject.get("resultCode");
        String message = (String) jsonObject.get("message");
        JSONArray jsonUserAlarmMsgstations = jsonObject.getJSONObject("data").getJSONArray("content");
        // 获取新增用户信息
        List<ListAlarmMsgstationVO> alarmMsgstationList = JSONObject.parseArray(jsonUserAlarmMsgstations.toJSONString(),
                ListAlarmMsgstationVO.class);

        System.out.println("response content:" + content);
        // 请求结果断言测试
        // 返回码
        Assertions.assertTrue(httpStatus == HttpStatus.OK.value());
        // 响应内容
        Assertions.assertAll("response content test",
                () -> Assertions.assertEquals(ResultCode.SUCCESS.getCode(), resultCode),
                () -> Assertions.assertEquals("查询成功", message), () -> Assertions.assertNotNull(alarmMsgstationList));
        Assertions.assertTrue(content.contains("\"packageNum\":1"));
        Assertions.assertTrue(content.contains("\"packageSize\":10"));
    }

标签: sp2841a502角度传感器a502高精度电位计角度传感器

锐单商城拥有海量元器件数据手册IC替代型号,打造 电子元器件IC百科大全!

锐单商城 - 一站式电子元器件采购平台