设为首页 加入收藏

TOP

使用Java函数接口及lambda表达式隔离和模拟外部依赖更容易滴单测(四)
2018-03-08 09:05:46 】 浏览:875
Tags:使用 Java 函数 接口 lambda 表达式 隔离 模拟 外部 依赖 容易 单测
ollUrl = this.serviceUrl + "?scroll=600000"; while (true){ DataQueryBuilder dataQuery = new DataQueryBuilder(); dataQuery.setScroll_id(scrollId); JSONObject jsonResult = query(JSON.toJSONString(dataQuery), scrollUrl); scrollId = jsonResult.getString("scroll_id"); List<T> tmpList = getData.apply(jsonResult); if(tmpList.size() == 0){ break; } rsList.addAll(tmpList); } } catch (Exception e) { logger.error("getESDataException", e); } return rsList; }

咋一看,似乎无从下手。别急,一步步来。

提取依赖变量和依赖函数

很容易看到,这个方法两次调用了 query, 可以先将 query 隔离出来,变成:

public <T> List<T> queryEsData(QueryBuilder initQuery, Function<JSONObject, List<T>> getData) {
        return queryEsDataInner(initQuery, this::query, getData);
    }

不过, 外部实例变量 this.serviceUrl 还在 queryEsDataInner 里面,会破坏 queryEsDataInner 的纯粹性,因此,要把这两个URL提取出来,放到 queryEsData 里传入给 queryEsDataInner. 效果应该是这样:

public <T> List<T> queryEsData(QueryBuilder initQuery, Function<JSONObject, List<T>> getData) {
        String initUrl = this.serviceUrl + "?search_type=scan&scroll=600000";
        String scrollUrl = this.serviceUrl + "?scroll=600000";
        return queryEsDataInner(initQuery, initUrl, scrollUrl, this::query, getData);
    }

public <T> List<T> queryEsDataInner(QueryBuilder initQuery, String initUrl, String scrollUrl,
                                   BiFunction<String, String, JSONObject> query,
                                   Function<JSONObject, List<T>> getData) {
        try {
            JSONObject result = query.apply(initQuery.toJsonString(), initUrl);
            logger.info("ES search init result: " + result.toJSONString());
            String scrollId = result.getString("scroll_id");
            if (scrollId == null) {
                return new ArrayList<>();
            }

            List rsList = new ArrayList();
            while (true){
                DataQueryBuilder dataQuery = new DataQueryBuilder();
                dataQuery.setScroll_id(scrollId);
                JSONObject jsonResult = query.apply(JSON.toJSONString(dataQuery), scrollUrl);
                scrollId = jsonResult.getString("scroll_id");
                List<T> tmpList = getData.apply(jsonResult);
                if(tmpList.size() == 0){
                    break;
                }
                rsList.addAll(tmpList);

            }
            return rsList;

        } catch (Exception e) {
            logger.error("getESDataException", e);
            return new ArrayList<>();
        }
    }

queryEsData 不纯粹没关系,反正它就是个壳。 仅这一步,就让 queryEsDataInner 方法变成了独立方法,不再依赖于任何外部变量和外部service,也不依赖于调用函数。不过 queryEsDataInner 会有点丑:有五个参数。 丑是丑了点,不过单测相对比较好写了。这里的 getData 动态生成不同的结果以便退出,因此用了点技巧,见代码:

@Test
    public void testQueryEsDataInner() {

        HttpEsClient esClient = new HttpEsClient();
        List empty = esClient.queryEsDataInner(new QueryBuilder(), "initUrl", "", (q, u) -> new JSONObject(), (jo) -> new ArrayList());
        Assert.assertEquals(0, empty.size());

        JSONObject jo = new JSONObject();
        List<Integer> list = Arrays.asList(1,2,3);
        jo.put("scroll_id", "1");
        jo.put("list", list);

        List result = esClient.queryEsDataInner(new QueryBuilder(), "initUrl", "scrollUrl", (q, u) -> jo, this::dyGetData);
        Assert.assertArrayEquals(new Integer[]{1,2,3,1,2,3}, result.toArray(new Integer[0]));
    }

    private static int i = 2;

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

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目