无法读取Mocked Java.io.Reader

时间:2016-08-02 20:02:46

标签: junit mockito java-io

我想用Mockito测试以下代码:

public static String funcToTest(String query) throws Exception {
    String url = Config.getURL(serviceName);
    HttpClient client = new HttpClient();
    HttpMethod method = new GetMethod(url);
    String resultantString= "";

    method.setQueryString(URIUtil.encodeQuery(query));
    client.executeMethod(method);
    if (method.getStatusCode() == HttpStatus.SC_OK) {
        Reader reader = new InputStreamReader(method
                    .getResponseBodyAsStream());
        int charValue = 0;
        StringBuffer sb = new StringBuffer(1024);
        while ((charValue = reader.read()) != -1) {
            sb.append((char) charValue);
        }
        resultantString = sb.toString();
    }
    method.releaseConnection();
    return resultantString;
}

我创建了如下测试:

@Test
public void testFunc() throws Exception{
    HttpMethod method =  Mockito.mock(HttpMethod.class);
    InputStream inputStream = Mockito.mock(InputStream.class);
    Reader reader = Mockito.mock(Reader.class);

    when(method.getResponseBodyAsStream()).thenReturn(inputStream);
    PowerMockito.whenNew(Reader.class).withArguments(eq(inputStream)).thenReturn(reader);

    Mockito.when(reader.read()).thenReturn((int)'1', -1);


    String actualResult = cls.funcToTest("");
    String expected = "1";
    assertEquals(expected, actualResult);
}

但是reader.read()方法没有返回1.相反,它总是返回-1。我应该如何模拟Reader以便read()方法将返回-1以外的其他内容。

感谢。

2 个答案:

答案 0 :(得分:1)

首先,您的测试代码正在进行大量.class模拟以模拟函数局部变量/引用。模拟用于类依赖,而不用于函数局部变量。

如上所述,您无法单独使用模拟来测试您的函数funcToTest。如果不愿意使用真实对象,则需要重写此函数 - HttpMethod& Reader

如果您希望模拟对这些对象的调用并使用此get方法替换new的代码,则需要在此函数外部使用new删除对象创建代码。 e.g。

protected HttpMethod getHttpMethod(String Url){
   return new GetMethod(url);
}

另外,我没有看到你嘲笑这一行的虚假URL - 这似乎是单元测试的必要条件。

String url = Config.getURL(serviceName);

在函数外部创建对象创建代码之后,您需要创建一个新类而不是扩展您的SUT(测试对象)并覆盖这些方法(getHttpMethod)以提供伪造/模拟实例

您需要编写类似的方法来获取Reader实例。

然后你测试这个新类 - 从你的SUT扩展,因为不需要测试对象创建逻辑。

如果不在函数外部使用对象创建代码,我就不会看到mockito模仿它的方法。

希望它有所帮助!!

答案 1 :(得分:0)

它必须有效,对不起是什么让你有点困惑)

// annotations is very important, cls I your tested class name, i assume cls is yours

@RunWith(PowerMockRunner.class)
@PrepareForTest({cls.class})
public class PrinterTest {

    @Test
    public void print() throws Exception {

        String url = "";
        GetMethod method = Mockito.mock(GetMethod.class);
        InputStream inputStream = Mockito.mock(InputStream.class);
        InputStreamReader reader = Mockito.mock(InputStreamReader.class);

        Mockito.when(method.getResponseBodyAsStream()).thenReturn(inputStream);
        //forgot about it )
        PowerMockito.whenNew(GetMethod.class).withArguments(eq(url)).thenReturn(method);
        PowerMockito.whenNew(InputStreamReader.class).withArguments(eq(inputStream)).thenReturn(reader);


        Mockito.when(reader.read()).thenReturn((int) '1', -1);
        when(method.getStatusCode()).thenReturn(HttpStatus.SC_OK);

        String actualResult = cls.funcToTest(url);
        String expected = "1";
        assertEquals(expected, actualResult);
    }


}