标签:mock 方法 状态 启动 Servle content article web 规则
一、本节主要记录模拟测试、单元测试:
二、mock 测试
在面向对象程序设计中,模拟对象(英语:mock object,也译作模仿对象)是以可控的方式模拟真实对象行为的假的对象。比如:对象B依赖于对象A,但是A代码还没写是一个空类空方法不能用,我们来mock一个假的A来完成测试。
/** * @author Levi * @date 2019/10/4 21:09 */ //@Transactional @Slf4j @SpringBootTest public class MockTest { private MockMvc mockMvc; //它是不在spring容器中的,需要手动引入 @Before public void setUp() { mockMvc = MockMvcBuilders.standaloneSetup(new AnimalController()).build(); } @Test public void saveArticle() throws Exception { //直接将前面请求的例子粘贴过来会自动分行 String article = "{\n" + " \"id\": 1,\n" + " \"name\": \"pig\",\n" + " \"type1\": \"\",\n" + " \"birthDate\":\"2019-10-04T05:10:10\",\n" + " \"animalList\":[{\"name\":\"dog\",\"type\":5},{\"name\":\"dog\",\"type\":10}]\n" + "}"; MvcResult result = mockMvc.perform( MockMvcRequestBuilders.request(HttpMethod.POST, "/rest/animals") .contentType("application/json").content(article)) .andExpect(MockMvcResultMatchers.status().isOk())//返回状态200为成功 .andExpect(MockMvcResultMatchers.jsonPath("$.data.name").value("pig"))//返回属性name为pig .andExpect(MockMvcResultMatchers.jsonPath("$.data.animalList[0].type").value(5))//返回属性type需要为5 .andDo(print()) .andReturn(); log.info(result.getResponse().getContentAsString()); } }
测试代码;
返回结果;
是用来创建Spring的上下文ApplicationContext,保证测试在上下文环境里运行。单独使用@SpringBootTest不会启动servlet容器。所以只是用SpringBootTest 注解,不可以使用@Resource和@Autowired等进行依赖注入(准确的说是可以使用,但被注解的bean为null)。
可以使单元测试进行事务回滚,以保证数据库表中没有因测试造成的垃圾数据,再就是保证单元测试可以反复执行;
不要在 Spring Boot 集成测试中使用 @Transactional
不推荐使用,他会删表,不会删除数据,他的事务是在内存中进行的,模拟的结果是不正确的,和真实环境有差距的;
在测试类上面额外加上这样两个注解,mockMvc使用@Resource自动注入,删掉Before注解及setUp函数
添加
@RunWith(SpringRunner.class) @AutoConfigureMockMvc 注解后,即在spring中运行;
RunWith方法为我们构造了一个的Servlet容器运行运行环境,并在此环境下测试。然而为什么要构建servlet容器?因为使用了依赖注入,注入了MockMvc,在上个例子里面是我们自己构建的。而@AutoConfigureMockMvc注解,该注解表示 MockMvc由我来构建,你只负责用就可以了。这种写法是为了让测试在Spring容器环境下执行。Spring的容器环境是啥呢?比如常见的 Service Dao 都是Spring容器里的bean,装载到容器里面,都可以使用@Resource和@Autowired来引用。
注入并使用了@Runwith,少了这个注解,service注入不进去,会报空指针
1、在RunWith的AutoConfigureMockMvc注解的共同作用下,启动了SpringMVC的运行容器。并且把项目中所有的@Bean全部都注入进来。把所有的bean都注入进来是不是略显臃肿,真实的单元测试有可能上千个,这样会拖慢单元测试的效率。如果我只是想测试一下web层,或者说的控制层Controller,怎么办?或者说我只想测试一下ArticleRestController,你不要把应用中所有的bean都注入。
/** * 在轻量级容器中的测试 * @author Levi * @date 2019/10/4 21:09 */ //@Transactional @Slf4j //@SpringBootTest @WebMvcTest //注入所有controller 甚至可以注入指定controller @WebMvcTest(AnimalController.class) @RunWith(SpringRunner.class) @AutoConfigureMockMvc public class MockTestSimple { @Resource private MockMvc mockMvc; @MockBean private AnimalService animalService; @Test public void saveArticle() throws Exception { String animal = "{\n" + " \"id\": 1,\n" + " \"name\": \"pig\",\n" + " \"type\": \"\",\n" + " \"birthDate\":\"2019-10-04T05:10:10\",\n" + " \"animalList\":[{\"name\":\"dog\",\"type\":5},{\"name\":\"dog\",\"type\":10}]\n" + "}"; log.error("animal"+animalService.saveAnimal(null)); ObjectMapper objectMapper = new ObjectMapper(); Animal animalObj = objectMapper.readValue(animal,Animal.class); //打桩--当controller调用改service时,模拟返回一个ok when(animalService.saveAnimal(animalObj)).thenReturn("ok"); MvcResult result = mockMvc.perform( MockMvcRequestBuilders.request(HttpMethod.POST, "/rest/animals") .contentType("application/json").content(animal)) .andExpect(MockMvcResultMatchers.status().isOk())//返回状态200为成功 .andExpect(MockMvcResultMatchers.jsonPath("$.data.name").value("pig"))//返回属性name为pig .andExpect(MockMvcResultMatchers.jsonPath("$.data.animalList[0].type").value(5))//返回属性type需要为5 .andDo(print()) .andReturn(); log.info(result.getResponse().getContentAsString()); } }
可以查看到电泳到的sevice 不是“animal测试”,而是“ok”
springboot2.0入门(四)----mock模拟测试+单元测试
标签:mock 方法 状态 启动 Servle content article web 规则
原文地址:https://www.cnblogs.com/liweiweicode/p/11623566.html