SpringMVC测试代码指的是不需要启动springmvc项目,就可以用测试代码访问Controller。
但是要注意: SpringMVC测试代码是基于SpringBoot环境下的, 所以项目必须用SpringBoot构建
注意:控制器层用SpringMVC测试代码(专业叫做MockMVC)
一、添加依赖包:
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.5.9</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.zyq</groupId>
<artifactId>mvc_test</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>mvc_test</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
二、设置编码:
# 执行测试时, 响应的json结果数据中如果包含中文,可能会出现乱码,需要在配置文件中配置编码
server.servlet.encoding.force=true
server.servlet.encoding.charset=utf-8
# yml文件中设置格式如下:
#server:
# servlet:
# encoding:
# force:true
# charset:utf-8
三、AdminController.java
package com.zyq.mvcTest.controller;
import com.fasterxml.jackson.annotation.JsonInclude;
import lombok.Data;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.io.Serializable;
@RestController
@RequestMapping(value = "/admins", produces = "application/json; charset=utf-8")
public class AdminController {
// 注意:暂时使用@RequestMapping,不要使用@PostMapping,以便于直接在浏览器中测试
// http://localhost:8080/admins/add-new?username=root&password=1234
@PostMapping("/add-new")
public JsonResult<Void> addNew(@Validated AdminSimpleVO AdminSimpleVO) {
System.out.println("模拟业务层的注册代码::此处应该要调用" +
"AdminServiceImpl的addnew()方法,保存用户:"+AdminSimpleVO);
//adminService.addNew(AdminSimpleVO);
return JsonResult.ok();
}
@RequestMapping("/login") // 暂时使用@RequestMapping,后续改成@PostMapping
public JsonResult<AdminSimpleVO> login(@Validated AdminSimpleVO adminSimpleVO) {
System.out.println("模拟业务层的登录代码::此处应该要调用" +
"AdminServiceImpl的login()方法,验证用户信息:"+adminSimpleVO);
//AdminSimpleVO adminSimpleVO = adminService.login(adminSimpleVO);
return JsonResult.ok(adminSimpleVO);
}
}
// Data Transfer Object
@Data
class AdminSimpleVO implements Serializable {
private Long id;
private String username;
private String password;
private Integer isEnable;
private String nickname;
private String avatar;
private String phone;
private String email;
private String description;
}
@Data
@JsonInclude(JsonInclude.Include.NON_NULL)
class JsonResult<T> implements Serializable {
// 状态码,例如:200
private Integer state;
// 消息,例如:"登录失败,用户名不存在"
@JsonInclude(JsonInclude.Include.NON_NULL)
private String message;
// 数据
@JsonInclude(JsonInclude.Include.NON_NULL)
private T data;
private JsonResult() {}
public static JsonResult<Void> ok() {
// JsonResult jsonResult = new JsonResult();
// jsonResult.setState(1);
// return jsonResult;
return ok(null);
}
public static <T> JsonResult<T> ok(T data) {
JsonResult<T> jsonResult = new JsonResult<>();
jsonResult.setState(200);
jsonResult.setData(data);
return jsonResult;
}
public static JsonResult<Void> fail(int statusCode, String message) {
JsonResult<Void> jsonResult = new JsonResult<>();
jsonResult.setState(statusCode);
jsonResult.setMessage(message);
return jsonResult;
}
}
四、测试代码:
注意:测试类必须写在项目根包下(因为要参与组件扫描,需要注入mockMvc等对象)
package com.zyq.mvcTest.controller;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.http.MediaType;
import org.springframework.test.context.jdbc.Sql;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.result.MockMvcResultHandlers;
import org.springframework.test.web.servlet.result.MockMvcResultMatchers;
@SpringBootTest
@AutoConfigureMockMvc // 自动配置MockMvc
public class AdminControllerTest {
@Autowired(required = false)
MockMvc mockMvc; // Mock单词意思是模拟
//@Sql({"classpath:truncate.sql", "classpath:insert_data.sql"})
@Test
public void testLoginSuccessfully() throws Exception {
// 准备测试数据,不需要封装
String username = "admin001";
String password = "123456";
// 请求路径,不需要写协议、服务器主机和端口号
String url = "/admins/login";
// 执行测试
// 以下代码相对比较固定
mockMvc.perform(
MockMvcRequestBuilders.post(url) // 根据请求方式决定调用的方法
.contentType(MediaType.APPLICATION_FORM_URLENCODED)
// 请求数据的文档类型,例如:application/json; charset=utf-8
// application/x-www-form-urlencoded;charset=UTF-8
.param("username", username)
// 请求参数,有多个时,多次调用param()方法
.param("password", password)
.accept(MediaType.APPLICATION_JSON))
// 接收的响应结果的文档类型,注意:perform()方法到此结束
.andExpect( // 预判结果,类似断言
MockMvcResultMatchers
.jsonPath("state")//预判响应JSON结果中将有名为state的属性
.value(200))
//预判响应的JSON结果中名为state的属性的值,注意:andExpect()方法到此结束
.andDo( // 需要执行某任务
MockMvcResultHandlers.print()); // 打印日志
}
}