SpringBoot测试步骤
在src/main下新建一个实例User
@Component
public class User {
}
src/test下创建测试类测试:
@RunWith(SpringRunner.class)
@SpringBootTest
public class UserTest {
@Autowired
public ApplicationContext context;
@Test
public void testNotNull(){
Assert.assertNotNull(context.getBean(User.class));
}
}
在src/test下新建二个类,我们发现分别使用@TestComponent和@TestConfiguration二个注解修饰,这些类只在测试环境生效
@TestComponent
public class Cat {
public void index(){
System.out.println("cat index");
}
}
@TestConfiguration
public class TestBeanConfiguration {
@Bean
public Runnable createRunnable(){
return () -> System.out.println("=====createRunnable=======");
}
}
测试类:
@RunWith(SpringRunner.class)
@SpringBootTest(classes = {TestBeanConfiguration.class,Cat.class})
public class TestApplication {
@Autowired
public ApplicationContext context;
@Test
public void testNotNull(){
Runnable runnable = context.getBean(Runnable.class);
runnable.run();
System.out.println("--------");
Cat cat = context.getBean(Cat.class);
cat.index();
}
}
需要在@SpringBootTest注解的参数classes中加入参数,表示将某些类纳入测试环境的容器中。
springboot会只会读取到src/test/resources下的配置,不会读到正式环境下的配置文件(跟以前1.4.*版本的不一样,以前是优先读取测试环境配置文件,然后读取正式环境的配置)
@RunWith(SpringRunner.class)
@SpringBootTest
public class EnvTest {
@Autowired
public Environment environment;
@Test
public void testValue(){
Assert.assertEquals("zhihao.miao",environment.getProperty("developer.name"));
}
}
除了在配置文件中设置属性,测试环境加载一些配置信息的二种方式:
第一种使用@SpringBootTest注解,注解参数properties指定其value值,第二种使用EnvironmentTestUtils.addEnvironment方法进行设置。
@RunWith(SpringRunner.class)
@SpringBootTest(properties = {"app.version=1.0"})
public class EnvTest2 {
@Autowired
private ConfigurableEnvironment environment;
@Before
public void init(){
EnvironmentTestUtils.addEnvironment(environment,"app.admin.user=zhangsan");
}
@Test
public void testApplication(){
Assert.assertEquals("1.0",environment.getProperty("app.version"));
Assert.assertEquals("zhangsan",environment.getProperty("app.admin.user"));
}
}
正式环境只是一个接口,并没有实现,也并没有纳入spring容器进行管理。
public interface UserDao {
Integer createUser(String userName);
}
测试
@RunWith(SpringRunner.class)
public class UserDaoTest {
//使用MockBean是因为此时容器中没有UserMapper这个对象
@MockBean
public UserDao userDao;
//使用BDDMockito对行为进行预测,
@Before
public void init(){
BDDMockito.given(userDao.createUser("admin")).willReturn(1);
BDDMockito.given(userDao.createUser("")).willReturn(0);
BDDMockito.given(userDao.createUser(null)).willThrow(NullPointerException.class);
}
@Test(expected=NullPointerException.class)
public void testCreateUser() {
Assert.assertEquals(Integer.valueOf(1),userDao.createUser("admin")) ;
Assert.assertEquals(Integer.valueOf(0),userDao.createUser("")) ;
Assert.assertEquals(Integer.valueOf(1),userDao.createUser(null)) ;
}
}
第一种方式:
定义一个Controller,用作测试:
@RestController
public class UserController {
private Logger logger = LoggerFactory.getLogger(getClass());
@GetMapping("/user/home")
public String home(){
logger.info("user home");
return "user home";
}
@GetMapping("/user/show")
public String show(@RequestParam("id") String id){
logger.info("book show");
return "show"+id;
}
}
使用浏览器访问
http://localhost:8080/user/home
http://localhost:8080/user/show?id=100
使用测试类测试
@RunWith(SpringRunner.class)
//指定web环境,随机端口
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class UserControllerTest {
@LocalServerPort
private int port;
//这个对象是运行在web环境的时候加载到spring容器中
@Autowired
private TestRestTemplate testRestTemplate;
@Test
public void testHome(){
String context = testRestTemplate.getForObject("/index",String.class);
Assert.assertEquals("hello world",context);
}
@Test
public void testShow(){
String context = testRestTemplate.getForObject("/index?id=1",String.class);
Assert.assertEquals("hahaha",context);
}
}
第二种方式,使用@WebMvcTest注解
@RunWith(SpringRunner.class)
@WebMvcTest(controllers = UserController.class)
public class UserControllerTest2 {
@Autowired
public MockMvc mockMvc;
@Test
public void testHome() throws Exception {
mockMvc.perform(MockMvcRequestBuilders.get("/index")).andExpect(MockMvcResultMatchers.status().isOk());
mockMvc.perform(MockMvcRequestBuilders.get("/index")).andExpect(MockMvcResultMatchers.status().isOk()).andExpect(MockMvcResultMatchers.content().string("user home"));
}
@Test
public void testShow() throws Exception {
mockMvc.perform(MockMvcRequestBuilders.get("/index").param("id", "1")).andExpect(MockMvcResultMatchers.status().isOk());
mockMvc.perform(MockMvcRequestBuilders.get("/index").param("id", "1")).andExpect(MockMvcResultMatchers.status().isOk()).andExpect(MockMvcResultMatchers.content().string("show400"));
}
}
@WebMvcTest 不需要运行在web环境下,但是,需要指定controllers,表示需要测试哪些controllers。
这种方式只测试controller,controller里面的一些依赖,需要你自己去mock
@WebMvcTest 不会加载整个spring容器。
第三种方式
使用@SpringBootTest()与@AutoConfigureMockMvc结合,@SpringBootTest使用@SpringBootTest加载测试的spring上下文环境,@AutoConfigureMockMvc自动配置MockMvc这个类,
/**
* @SpringBootTest 不能和 @WebMvcTest 同时使用
* 如果使用MockMvc对象的话,需要另外加上@AutoConfigureMockMvc注解
*/
@RunWith(SpringRunner.class)
@SpringBootTest()
@AutoConfigureMockMvc
public class UserControllerTest3 {
@Autowired
private MockMvc mvc;
@Test
public void testHome() throws Exception {
mvc.perform(MockMvcRequestBuilders.get("/index")).andExpect(MockMvcResultMatchers.status().isOk());
mvc.perform(MockMvcRequestBuilders.get("/index")).andExpect(MockMvcResultMatchers.status().isOk()).andExpect(MockMvcResultMatchers.content().string("user home"));
}
@Test
public void testShow() throws Exception {
mvc.perform(MockMvcRequestBuilders.get("/index").param("id", "1")).andExpect(MockMvcResultMatchers.status().isOk());
mvc.perform(MockMvcRequestBuilders.get("/index").param("id", "1")).andExpect(MockMvcResultMatchers.status().isOk()).andExpect(MockMvcResultMatchers.content().string("show400"));
}
}
一个注解可以使测试类可以自动配置MockMvc这个类。