3

单元测试在开发的过程中可能会被很多的人所忽略,其实也不是真的被忽略可能是由于巨大的业务压力而导致没有时间去写那些测试,而是直接通过集成测试完没问题就提交给测试进行测试后上线了。这样其实很多时候反而会浪费大量的时间在测试上面,而适量的写好单元测试有以下一些优势:

  • 有单元测试可能会提高整个集成测试的进度而且最重要的是做到对自己写的代码知根知底,更有底气的推到线上去。
  • 在对逻辑进行重构的时候可以直接通过单元测试能把控整个重构的逻辑不发生重大偏差,给后来者造福了。

服务单元测试

下面是一段获取缓存逻辑的单元测试。CacheManager中封装了逻辑从缓冲中取数据,如果数据没有取到则从repositoryCache.loadStoreByKey(key)中load数据。

public void getValueIfNullLoadTest() {
    /* 从repository里面取数据 */
    RepositoryCache repositoryCache = mock(RepositoryCache.class);
    String key = anyString();
    when(repositoryCache.loadStoreByKey(key)).thenReturn("test");
    when(repositoryCache.getCacheName()).thenReturn(Constants.CACHE);

    CacheManager.addRepository(repositoryCache);
    String value = CacheManager.getValueIfNullLoad(Constants.CACHE, key, String.class);

    Assert.assertTrue(StringUtils.equals(value, "test"));

    /* 从缓存中取 */
    value = CacheManager.getValueByCache(Constants.CACHE, key, String.class);
    Assert.assertTrue(StringUtils.equals(value, "test"));

}
  • mockrepositoryCache,当调用repositoryCacheloadStoreByKey或者getCacheName方法后返回测试数据。
  • 后面执行CacheManager.getValueIfNullLoad中正常的业务逻辑。
  • 最后判断结果是否符合预期。

controller单元测试

上面一小节只是针对普通的服务单元进行测试,但是遇到http的接口测试就无能为力了,下面来介绍下如果写http接口的单元测试。

public class UserControllerUnitTest {

    private MockMvc mockMvc;

    @Mock
    private UserService userService;

    @InjectMocks
    private UserController userController;

    @Before
    public void init(){
        MockitoAnnotations.initMocks(this);
        mockMvc = MockMvcBuilders
                .standaloneSetup(userController)
                .addFilters(new CORSFilter())
                .build();
    }

    @Test
    public void test_get_all_success() throws Exception {
        List<User> users = Arrays.asList(
                new User(1, "Daenerys Targaryen"),
                new User(2, "John Snow"));
        when(userService.getAll()).thenReturn(users);
        mockMvc.perform(MockMvcRequestBuilders.get("/users"))
                .andExpect(MockMvcResultMatchers.status().isOk())
                .andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8_VALUE))
                .andExpect(mvcResult -> {
                    String responseStr = mvcResult.getResponse().getContentAsString();
                    //针对结果进行验证。
                });
        Mockito.verify(userService, times(1)).getAll();
        Mockito.verifyNoMoreInteractions(userService);
    }

}
  • mock一个服务userService
  • InjectMocks userController后通过MockitoAnnotations.initMocks(this)userService这个mock的服务注入到userController中。
  • MockMvcBuilders.standaloneSetup(userController).build(); 创建MockMvc
  • 后面就是模拟发送http请求,然后验证response的操作和上一节的类似。
  • 最后是验证mock服务的接口调用次数。

总结

可能你也会在项目中看到很多的单元测试,但是随着项目的迭代那些单元测试已经失效,又或者是你会看到在进行单元测试的时候会去启动整个项目容器去做运行,不过只要有就是好的,后面在进行项目迭代的过程中别忘了把unit test写上吧。

参考

Unit Test Spring MVC Rest Service: MockMVC, JUnit, Mockito


博予liutxer
266 声望14 粉丝

专业写代码的代码仔。