Java 单元测试webapi消费模块

Java 单元测试webapi消费模块,java,api,unit-testing,Java,Api,Unit Testing,我的代码是API的使用者(www.abc.com/public/news/apple.json)。作为回报,我得到一个json数组,然后将其解析并填充到我自己的数据结构中。负责执行此操作的代码是: public Map<String,List<NewsItem>> populateNewsArray() throws Exception { url = domain + newsApiStr; Inp

我的代码是API的使用者(www.abc.com/public/news/apple.json)。作为回报,我得到一个json数组,然后将其解析并填充到我自己的数据结构中。负责执行此操作的代码是:

    public Map<String,List<NewsItem>> populateNewsArray() throws Exception
        {
            url = domain + newsApiStr;
            InputStream stream = getNews(url, true);

           //jackson library object mapper
           ObjectMapper mapper = new ObjectMapper();

          //NewsApiObject class implements the structure of the json array returned.
           List<NewsApiObject> mappedData = mapper.readValue(stream, NewsApiObject.class));

           //populate the properties in a HashMap.
          //return HashMap
     }

     public InputStream getNews(String request, boolean bulk) throws Exception
     {
        URL url = new URL(request); 
        connection = (HttpURLConnection) url.openConnection();           
        connection.setDoOutput(true);
        connection.setInstanceFollowRedirects(false);
        connection.setRequestMethod("GET"); 
        connection.setRequestProperty("Content-Type", "text/plain"); 
        connection.setRequestProperty("charset", "utf-8");
        connection.connect();

        return connection.getInputStream();
     }
公共映射PopulateNewArray()引发异常
{
url=domain+newsApiStr;
InputStream=getNews(url,true);
//jackson库对象映射器
ObjectMapper mapper=新的ObjectMapper();
//NewsApiObject类实现返回的json数组的结构。
List mappedData=mapper.readValue(stream,NewsApiObject.class));
//在HashMap中填充属性。
//返回哈希映射
}
公共InputStream getNews(字符串请求,布尔批量)引发异常
{
URL=新URL(请求);
connection=(HttpURLConnection)url.openConnection();
connection.setDoOutput(真);
connection.setInstanceFollowDirections(false);
connection.setRequestMethod(“GET”);
setRequestProperty(“内容类型”、“文本/普通”);
setRequestProperty(“字符集”、“utf-8”);
connection.connect();
返回连接。getInputStream();
}

正如您所看到的,我不是api的控制器,只是消费者。据说,在单元测试中,不需要进行http请求。在这个场景中,如何对populateNewsArray()函数进行单元测试,以查看对象映射是否正确(没有任何异常),以及是否返回了有效的hashmap

我将创建一个子类并覆盖方法
getNews(…)
。在子类中,您可以为测试返回一个
InputStream


由于在单元测试中不应该依赖于某些外部文件,并且为了获得更好的可测试设计,我还将更改
getNews(…)
方法以返回某种类型的值,这些值可以由映射程序进一步处理。

我将创建一个子类并覆盖该方法
getNews(…)
。在子类中,您可以为测试返回一个
InputStream


由于在单元测试中您不应该依赖于某些外部文件,并且为了获得更好的可测试设计,我还将更改
getNews(…)
方法以返回某种类型的值,这些值可以由映射程序进一步处理。

您应该将
getNews()
提取到单独的接口中,例如新闻阅读器(虽然单词
Reader
在JDK中有特定的含义,但我喜欢这个名字…)

然后根据您的代码使用
HttpURLConnection
实现该接口,并更新您的代码以允许注入该特定接口。然后,如果您需要测试代码如何处理
InputStream
,您可以创建一个模拟的
NewsReader
,它返回一个
InputStream
,其中包含已知的con帐篷


请记住要以高内聚性为目标:您的类不应该是HTTP客户端和流解析器。

您应该将
getNews()
提取到一个单独的接口中,例如新闻阅读器(尽管
Reader
这个词在JDK中有特定的含义,我喜欢这个名称…)

然后根据您的代码使用
HttpURLConnection
实现该接口,并更新您的代码以允许注入该特定接口。然后,如果您需要测试代码如何处理
InputStream
,您可以创建一个模拟的
NewsReader
,它返回一个
InputStream
,其中包含已知的con帐篷


请记住要以高内聚性为目标:您的类不应该是HTTP客户端和流解析器。

顺便说一句,david,如果我确实创建了一个新闻阅读接口,那么我如何测试PopulateWarray()func?我是否需要完全更改函数并删除getNews调用,以便对其进行单元测试?@Salmanmahmood
PopulatenWarray
调用
NewsReader.getNews
。您可以插入一个返回
ByteArrayInputStream
包含已知JSON。如何确保在测试时调用模拟对象,而不是真正的实现(进行网络调用)?使用依赖项注入。您可以手动执行,也可以使用IoC容器(Spring/Guice)。这里的关键概念是将新闻阅读器注入到类中。例如,在主类中定义一个构造函数,该构造函数接受新闻阅读器实例。顺便说一句,david,如果我确实创建了一个用于新闻阅读的接口,那么我如何测试populateNewArray()func?我是否需要完全更改函数并删除getNews调用,以便对其进行单元测试?@Salmanmahmood
PopulatenWarray
调用
NewsReader.getNews
。您可以插入一个返回
ByteArrayInputStream
包含已知JSON。如何确保在测试时调用模拟对象,而不是真正的实现(进行网络调用)?使用依赖项注入。您可以手动执行,也可以使用IoC容器(Spring/Guice)。这里的关键概念是将新闻阅读器注入到类中。例如,在主类中定义一个构造函数,该构造函数接受新闻阅读器实例。
public interface NewsReader {
    InputStream getNews(String request, boolean bulk) throws Exception
}