java - 为被测依赖类创建 stub

标签 java unit-testing testing reflection

大家好!我有一个关于通过反射测试和生成依赖 stub 的小问题。因此,假设我有一个名为 UnderTest 的类:

class UnderTest{
/*field*/ 
SomeLogic someLogic; 
/*method, that i testing*/
List<MyObject> getCalculatedObjects(params) {/*logic,based on result getSomeStuff of someLogic*/    }
} 
class SomeLogic { 
List<String> getSomeStuff(String param) { /*Some complex and slow code, actually  don't want test this code, and want to use some reflection invocation handler*/ }
}

对我来说,重要的是不要更改遗留代码,这些代码不是为测试而设计的。而且我没有任何理由,除了测试将 SomeLogic 作为接口(interface)等等。 我不记得如何使用反射处理 someLogic 的方法调用。但是谷歌搜索对我没有帮助。

MainAPI 类是...我模块的主要 api。 NetworkProvider 长时间打开流操作,这就是为什么我想在我的本地文件上 stub 它。但不要在 NetworkProvider 上使用直接引用。再次为我的英语感到抱歉。

public class MainAPI {
    private final XPath xPath;
    private final ItemParser itemParser;
    private final ListItemsParser listItemsParser;
    private final DateParser dateParser;
    private final HtmlCleanUp htmlCleanUp;

    private final NetworkProvider networkProvider;


    public MainAPI(XPath xPath, ItemParser itemParser, ListItemsParser listItemsParser, DateParser dateParser, HtmlCleanUp htmlCleanUp, NetworkProvider networkProvider) {
        this.xPath = xPath;
        this.itemParser = itemParser;
        this.listItemsParser = listItemsParser;
        this.dateParser = dateParser;
        this.htmlCleanUp = htmlCleanUp;
        this.networkProvider = networkProvider;
    }

    public MainAPI() throws XPathExpressionException, IOException {
        dateParser = new DateParser();
        xPath = XPathFactory.newInstance().newXPath();
        networkProvider = new NetworkProvider();
        listItemsParser = new ListItemsParser(xPath, dateParser, item -> true);
        itemParser = new ItemParser(xPath, dateParser, networkProvider);
        htmlCleanUp = new HtmlCleanUpByCleaner();
    }

    public List<Item> getItemsFromSessionParsing(SessionParsing sessionParsing) {
        listItemsParser.setCondition(sessionParsing.getFilter());
        List<Item> result = new ArrayList<>();
        Document cleanDocument;
        InputStream inputStream;
        for (int currentPage = sessionParsing.getStartPage(); currentPage <= sessionParsing.getLastPage(); currentPage++) {
            try {
                inputStream = networkProvider.openStream(sessionParsing.getUrlAddressByPageNumber(currentPage));
            } catch (MalformedURLException e) {
                e.printStackTrace();
                break;
            }
            cleanDocument = htmlCleanUp.getCleanDocument(inputStream);
            List<Item> list = null;
            try {
                list = listItemsParser.getList(cleanDocument);
            } catch (XPathExpressionException e) {
                e.printStackTrace();
                break;
            }
            for (Item item : list) {
                inputStream = null;
                try {
                    inputStream = networkProvider.openStream("http://www.avito.ru" + item.getUrl());
                } catch (MalformedURLException e) {
                    e.printStackTrace();
                    break;
                }
                cleanDocument = htmlCleanUp.getCleanDocument(inputStream);
                try {
                    item.setDescription(itemParser.getDescription(cleanDocument));
                } catch (XPathExpressionException e) {
                    e.printStackTrace();
                }

            }
            result.addAll(list);
        }
        return result;
    }
}

public class NetworkProvider {
    private final ListCycleWrapper<Proxy> proxyList;

    public NetworkProvider(List<Proxy> proxyList) {
        this.proxyList = new ListCycleWrapper<>(proxyList);
    }

    public NetworkProvider() throws XPathExpressionException, IOException {
        this(new ProxySiteParser().getProxyList(new HtmlCleanUpByCleaner().getCleanDocument(new URL("http://www.google-proxy.net").openStream())));
    }

    public int getSizeOfProxy() {
        return proxyList.size();
    }

    public InputStream openStream(String urlAddress) throws MalformedURLException {
        URL url = new URL(urlAddress);

        while (!proxyList.isEmpty()) {
            URLConnection con = null;
            try {
                con = url.openConnection(proxyList.getNext());
                con.setConnectTimeout(6000);
                con.setReadTimeout(6000);
                return con.getInputStream();
            } catch (IOException e) {
                proxyList.remove();
            }
        }
        return null;
    }
}

最佳答案

您的类对测试的所有依赖项都可以使用其构造函数注入(inject),因此 stub 这些依赖项并注入(inject) stub 应该没有任何问题。你甚至不需要反射(reflection)。例如,使用 Mockito:

NetworkProvider stubbedNetworkProvider = mock(NetworkProvider.class);
MainAPI mainApi = new MainAPI(..., stubbedNetworkProvider);

如果你愿意,你也可以自己写一个 stub :

NetworkProvider stubbedNetworkProvider = new NetworkProvider(Collections.emptyList()) {
    // TODO override the methods to stub
};
MainAPI mainApi = new MainAPI(..., stubbedNetworkProvider);

关于java - 为被测依赖类创建 stub ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25711781/

相关文章:

java - 为什么不保留新实体?

java - 如何在java中解析 "HTTP Error 411. The request must be chunked or have a content length."

java - JavaCC 中的 Epsilon 定义

java - Scala 如何将模拟对象注入(inject) ScalatraFlatSpec

c# - 如何捕获传递的参数并在模拟方法中更改其值

java - 如何让 Java 应用程序以更多内存运行?

java - 从 Java 启动文件

C# 使用 Moq 从模拟存储库中删除项目

c# - xunit.runner.visualstudio 是否不适用于 Visual Studio

testing - 聚类 : Cluster validation