SpringBoot提供了一组方便使用的工具注解帮助开发人员测试应用。主要包括了以下两个模块
实践中直接使用spring-boot-starter-test则可以全部包含上述模块,同时还附赠JUnit、AssertJ、Hamcrest等工具库。
示例程序是一个简单的Springboot工程,工程中定义了UserController,该controller中使用了UserService。
@RestController
@RequestMapping("/user")
public class UserController {
@Autowired
private UserService userService;
@GetMapping("get-by-id/{id}")
public User getUserById(@PathVariable("id") Long id) {
User userById = userService.getUserById(id);
return userById;
}
}
@Component
public class UserService {
public User getUserById(Long id) {
//模拟返回user数据
User user = new User();
user.setId(id);
user.setName("wanger");
return user;
}
}
此时测试,也是用的最多
package com.zte.sdn.oscp;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.util.Assert;
import com.zte.sdn.oscp.contorl.User;
import com.zte.sdn.oscp.contorl.UserController;
@SpringBootTest
public class UserControlTest {
@Autowired
private UserController userControl;
@Test
public void testGetById() {
User userById = userControl.getUserById(1L);
Assert.notNull(userById, "user id not be null");
Assert.isTrue(userById.getId() == 1L, "user id not equals 1");
Assert.isTrue(userById.getName().equalsIgnoreCase("wanger"), "user name not equals wanger");
}
}
在Spring中当存在rest接口需要进行测试,但在不启动web容器前提下测试。
可以使用McokMvc的方法进行,如下:
package com.zte.sdn.oscp;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.json.AutoConfigureJsonTesters;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.json.JacksonTester;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.MvcResult;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.result.MockMvcResultMatchers;
import org.springframework.util.Assert;
import com.zte.sdn.oscp.contorl.User;
@SpringBootTest
@AutoConfigureMockMvc
@AutoConfigureJsonTesters
public class UserControllerWithMockMvcTest {
@Autowired
private JacksonTester<User> json;
@Test
void exampleTest(@Autowired MockMvc mvc) throws Exception {
MvcResult mvcResult = mvc.perform(MockMvcRequestBuilders.get("/user/get-by-id/{id}", 1L))
.andExpect(MockMvcResultMatchers.status().isOk())
// .andDo(MockMvcResultHandlers.print())
.andExpect(MockMvcResultMatchers.jsonPath("$.id").value(1L))
.andExpect(MockMvcResultMatchers.jsonPath("$.name").value("wanger"))
.andReturn();
String contentAsString = mvcResult.getResponse().getContentAsString();
User user = json.parseObject(contentAsString);
Assert.state(user.getId() == 1L, "id must be 1");
Assert.state(user.getName().equalsIgnoreCase("wanger"), "name must be wanger");
}
}
启动内嵌的Server
package com.zte.sdn.oscp;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.web.client.TestRestTemplate;
import org.springframework.util.Assert;
import com.zte.sdn.oscp.contorl.User;
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class UserControllerWithEmbedServerTest {
@Autowired
private TestRestTemplate restTemplate;
@Test
public void exampleTest() {
User user = this.restTemplate.getForObject("/user/get-by-id/{id}", User.class, 1L);
Assert.notNull(user, "user can not be null.");
Assert.isTrue(user.getId() == 1L, "user id not equals 1");
Assert.isTrue(user.getName().equalsIgnoreCase("wanger"), "user name not equals wanger");
}
}
@WebMvcTest只会扫描您定义的控制器和MVC基础设施,因此,如果您的控制器对服务层中的其他bean有一定的依赖性,那么在您自己加载该配置或为其提供模拟之前,测试将不会启动。这个速度要快得多,因为我们只加载你应用的一小部分。
package com.zte.sdn.oscp;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import org.junit.jupiter.api.Test;
import org.mockito.Mockito;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.result.MockMvcResultMatchers;
import com.zte.sdn.oscp.contorl.User;
import com.zte.sdn.oscp.service.UserService;
@WebMvcTest
//@Import(UserService.class)
public class UserControllerWithWebMvcTest {
@Autowired
private MockMvc mockMvc;
/**
* 使用WebMvnTest不会扫描注入
* 也可以使用@Import注入需要的Bean
*/
@MockBean
private UserService userService;
@Test
public void exampleTest() throws Exception {
User user = new User();
user.setId(1L);
user.setName("wanger");
Mockito.when(this.userService.getUserById(1L)).thenReturn(user);
this.mockMvc.perform(get("/user/get-by-id/{id}", 1L))
.andExpect(status().isOk())
.andExpect(MockMvcResultMatchers.jsonPath("$.id").value(1L))
.andExpect(MockMvcResultMatchers.jsonPath("$.name").value("wanger"));
}
}
@WebMvcTest注解内可以指定相关的Bean,测试启动也只会加载其指定的Bean,如下:
package com.zte.sdn.oscp;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.result.MockMvcResultMatchers;
import com.zte.sdn.oscp.contorl.User;
import com.zte.sdn.oscp.contorl.UserController;
import com.zte.sdn.oscp.service.UserService;
@WebMvcTest({UserController.class, UserService.class})
public class UserControllerWithWebMvc2Test {
@Autowired
private MockMvc mockMvc;
@Test
public void exampleTest() throws Exception {
User user = new User();
user.setId(1L);
user.setName("wanger");
this.mockMvc.perform(get("/user/get-by-id/{id}", 1L))
.andExpect(status().isOk())
.andExpect(MockMvcResultMatchers.jsonPath("$.id").value(1L))
.andExpect(MockMvcResultMatchers.jsonPath("$.name").value("wanger"));
}
}