zoukankan      html  css  js  c++  java
  • 单元测试和mock的使用

    单元测试

    在导师公司打工,做了一个版本,技术上虽然没学到什么新东西,但是至少明白公司开发的各个流程,尤其是在提测阶段十分痛苦。一个bug反复出现,不停的修改,不停的调试,十分折腾。总结了一下异常处理没有放到controller层,log的使用还不够,另外明白了单元测试的重要性。从前到后找bug实在是太过痛苦,应当用单元测试把bug扼杀在摇篮里。特此总结单元测试的方法和用到的技术,争取下一个版本做到0bug提测。

    包结构规范

    单元测试包结构和源码结构保持一致

    命名规范

    文件名

    被测试文件名+Test

    方法名

    test+方法名+情况说明

    不同单元测试类规范

    以下所有的单元测试都要使用assert进行断言,要注意分支覆盖率尽可能提高,基层基础测试类

     

    基础测试类,用于启动Springboot环境

    @RunWith(SpringRunner.class)
    @SpringBootTest
    public class MallProductApplicationTests {
    @Before
    public void setup() {
    你的装载逻辑
    }
    }

    setup方法

    每一个测试类都要有一个setup方法并用@Before注解,该方法用于装载测试时需要的属性

    Controller层

    使用MockMvc模拟http请求(见后面教程)

    public class TestAttrController extend MallProductApplicationTests{
    @Test
    public void AttrAddTest() {
    使用MockMVC来构造请求
    }
    }

    Service层

    注意断言即可

    Dao层

    注意加上注解@RollBack防止数据库污染,整个类加上@Transactional注解

    Mock的使用

    mock主要是在某个接口还尚未实现或者难以调用时来产生一个临时的实现类

    MockMVC

    MockMVC是Controller层测试时用于构造http请求模拟网络环境时用到的。由spring-test提供。在json请求场景中使用方法如下

    Get请求示例

    @WebAppConfiguration
    public class MockTest extends GulimallProductApplicationTests {
      private MockMvc mockMvc;
      @Autowired
      private WebApplicationContext wac;
      @Before
      public void setup() {
    mockMvc = MockMvcBuilders.webAppContextSetup(wac).build();
      }

      @Test
      public void testMockMvc() throws Exception {
          MvcResult result = mockMvc.perform(
                  MockMvcRequestBuilders.get("/product/category/list"))
                  .andExpect(MockMvcResultMatchers.jsonPath("$.code")//断言json返回值
                          .value(200))
                  .andReturn();
          String contentAsString = result.getResponse().getContentAsString();
          System.out.println(contentAsString);
      }
    }

     

    说明:setup用于向mockMvc传入当前web环境,可以使用mockmvc的.andExpect来进行断言,一般在json返回值中使用MockMvcResultMatchers.jsonPath静态方法断言json中的某个值是否满足,也可以通过下面的

    result.getResponse().getContentAsString();方法直接得到json字符串做后续处理

    post请求示例

        @Test
      public void testMockMvcPost() throws Exception {
          AttrGroupDto attrGroupDto = new AttrGroupDto();
          attrGroupDto.setAttrGroupName("a");
          attrGroupDto.setCatelogId(1L);
          attrGroupDto.setSort(1);
          attrGroupDto.setAttrGroupName("bb");
          attrGroupDto.setIcon("123123");
          MvcResult result = mockMvc.perform(
                  MockMvcRequestBuilders.post("/product/attrgroup/add")
                  .content(JSON.toJSONString(attrGroupDto)).contentType(MediaType.APPLICATION_JSON))
                  .andReturn();
          System.out.println(result.getResponse().getContentAsString());
      }

    使用mockito构造接口

    Mockito已经包含在了springboot-test-starter里不需要额外引入

    public class MockTest {
      AttrDao attrDao;
      @Before
      public void setup() {
          //初始化所有由mokito注解标注的对象
          MockitoAnnotations.initMocks(this);
          //mock AttrDao接口
          attrDao = Mockito.mock(AttrDao.class);
          AttrEntity attrEntity = new AttrEntity();
          attrEntity.setAttrId(10L);
          //定义行为
          Mockito.when(attrDao.selectAttrById(1L)).thenReturn(attrEntity);
      }
      @Test
      public void testMock() {
          AttrEntity attrEntity = attrDao.selectAttrById(1L);
          System.out.println(attrEntity);
      }
    }

    说明:首先需要装载接口类,然后用Mockito.when().thenReturn方法定义接口中方法的行为即可实现mock调用

    也可以使用注解注入

    public class MockTest {
      @Mock
      AttrDao attrDao;
      @Before
      public void setup() {
          //初始化所有由mokito注解标注的对象
          MockitoAnnotations.initMocks(this);
          //注解注入就不需要这句了
          //attrDao = Mockito.mock(AttrDao.class);
          AttrEntity attrEntity = new AttrEntity();
          attrEntity.setAttrId(10L);
          //定义行为
          Mockito.when(attrDao.selectAttrById(1L)).thenReturn(attrEntity);
      }
      @Test
      public void testMock() {
          AttrEntity attrEntity = attrDao.selectAttrById(1L);
          System.out.println(attrEntity);
      }
    }

     

    Assert的使用

    java自带的关键字assert十分僵硬,只能传入一个boolean值,而且断言失败后直接就推出了rollback也不能回滚,因此最好用junit中的Assert类

    assertEqual

    判断两者是否一致

        @Test
      public void assertEqualTest() {
          // 成功
          Assert.assertEquals(1L, 1L);
          // 失败
          Assert.assertEquals(1L, 2L);
          int[] a1 = new int[]{1,2,3};
          int[] a2 = new int[]{1,2,3};
          int[] a3 = new int[]{2,3,4};
          // 成功
          Assert.assertArrayEquals(a1, a2);
          //失败
          Assert.assertArrayEquals(a1, a3);
      }

    assertTrue, assertFalse

    直接判断boolean的值

        @Test
    public void testAssertTrueFalse() {
    assertTrue(1 == 1);
        assertFalse(1 == 2);
    }

    assertNull,assertNotNull

    就不多说了

    assertSame, assertNotSame

    判断两者对象引用是否相同

    assertThat

    这个是重点,可以传入一个hamcrest提供的Matcher接口来进行判断

    Assert.assertThat(obj, Matchers.xxx);

     

  • 相关阅读:
    树莓派系统Raspbian安装小结
    树莓派安装centos 7系统
    Ubuntu下安装SSH服务
    使用xUnit为.net core程序进行单元测试(4)
    使用xUnit为.net core程序进行单元测试(3)
    使用xUnit为.net core程序进行单元测试 -- Assert
    使用xUnit为.net core程序进行单元测试(1)
    用 Identity Server 4 (JWKS 端点和 RS256 算法) 来保护 Python web api
    asp.net core 2.0 查缺补漏
    "软件随想录" 读书笔记
  • 原文地址:https://www.cnblogs.com/PanYuDi/p/14968953.html
Copyright © 2011-2022 走看看