设为首页 加入收藏

TOP

使用Java函数接口及lambda表达式隔离和模拟外部依赖更容易滴单测(二)
2018-03-08 09:05:46 】 浏览:871
Tags:使用 Java 函数 接口 lambda 表达式 隔离 模拟 外部 依赖 容易 单测
map.put("total", (null == total) ? 0 : total); return map; }

要编写这个函数的单测,你需要 mock creativeService。对,mock 的目的实际上只是为了拿到模拟的 creativeDTOs 和 total 值,然后塞入 map。 最后验证 map 里是否有 rows 和 total 两个 key 以及值是否正确。

我讨厌 mock !引入一堆繁重的东西,mock 的代码并不比实际的产品代码少,而且很无聊 ! 对于懒惰的人来说,写更多跟产品和测试“没关系”的代码就是惩罚!有没有办法呢? 实际上,可以采用函数接口来隔离这些外部依赖服务。 见如下改写后的代码: getListFunc 表达了如何根据 CreativeQuery 得到 CreativeDO 的列表, getTotalFunc 表达了如何根据 CreativeQuery 得到 CreativeDO 的总数。 原来的 searchForSelect 方法只要传入两个 lambda 表达式即可。

public Map<String, Object> searchForSelect(@RequestParam(value = "k", required = false) String title,
                                               @RequestParam(value = "page", defaultValue = "1") Integer page,
                                               @RequestParam(value = "rows", defaultValue = "10") Integer pageSize) {
        CreativeQuery query = buildCreativeQuery(title, page, pageSize);
        return searchForSelect2(query,
                               (q) -> creativeService.search(q),
                               (q) -> creativeService.count(q));
    }

    public Map<String, Object> searchForSelect2(CreativeQuery query,
                                               Function<CreativeQuery, List<CreativeDO>> getListFunc,
                                               Function<CreativeQuery, Integer> getTotalFunc) {
        List<CreativeDO> creativeDTOs = getListFunc.apply(query);
        Integer total = getTotalFunc.apply(query);
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("rows", (null == creativeDTOs) ? new ArrayList<CreativeDO>() : creativeDTOs);
        map.put("total", (null == total) ? 0 : total);
        return map;
    }


    /*
     * NOTE: can be placed in class QueryBuilder
     */
    public CreativeQuery buildCreativeQuery(String title, Integer page, Integer pageSize) {
        CreativeQuery query = new CreativeQuery();
        query.setTitle(title);
        query.setPageNum(page);
        query.setPageSize(pageSize);
        return query;
    }

现在,如何编写单测呢? buildCreativeQuery 这个自不必说。 实际上,只需要对 searchForSelect2 做单测,因为这个承载了主要内容; 而 searchForSelect 只是流程的东西,通过联调就可以测试。单测代码如下:

public class CreativeControllerTest {

  CreativeController controller = new CreativeController();

  @Test
  public void testSearchForSelect2() {
    CreativeQuery creativeQuery = controller.buildCreativeQuery("haha", 1, 20);
    Map<String, Object> result = controller.searchForSelect2(creativeQuery,
                                                            (q) -> null , (q)-> 0);
    Assert.assertEquals(0, ((List)result.get("rows")).size());
    Assert.assertEquals(0, ((Integer)result.get("total")).intValue());

  }

}

注意到,这里使用了 lambda 表达式来模拟返回外部服务的返回结果,因为我们本身就用 Function 接口隔离和模拟了外部服务依赖。 细心的读者一定发现了: lambda 表达式,简直是单测的 Mock 神器啊!

It’s Time to Say Goodbye to Mock Test Framework !

改写业务代码

看一段常见的业务代码,通过外部服务获取订单的物流详情后,做一段处理,然后返回相应的结果。

private List<Integer> getOrderSentIds(long sId, String orderNo) {

    OrderParam param = ParamBuilder.buildOrderParam(sId, orderNo);
    PlainResult<List<OrderXXXDetail>> xxxDetailResult =
            orderXXXService.getOrderXXXDetailByOrderNo(param);
    if (!xxxDetailResult.isSuccess()) {
      return Lists.newArrayList();
    }
    List<OrderXXXDetail> xxxDetails = xxxDetailResult.getData();
    List<Integer> sentIds = Lists.newArrayList();
    xxxDetails.forEach(xxxDetail -> sentIds.add(xxxDetail.getId()));
    return sentIds;
  }

从第三行 if 到 return 的是一个不依赖于外部服务的独立函数。为了便于写单测,实际上应该将这一部

首页 上一页 1 2 3 4 5 下一页 尾页 2/5/5
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇深入Spring Boot: 怎样排查 java... 下一篇如何编写相对标准的后端项目(二..

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目