java - 如何使用 mockito 或 powermock 模拟局部变量

标签 java mocking mockito junit4 powermock

我有这样的场景

InputStreamReader reader = new InputStreamReader(getFileAsStream(resourceResolver, iconpath));
                BufferedReader bReader = new BufferedReader(reader);

我一直 mock 到这里

getFileAsStream(resourceResolver, iconpath)

现在我有一个读者

 BufferedReader bReader = new BufferedReader(reader);

但是当我执行这一行时,我得到 null 并且无法前进

  while ((iconEntry = bReader.readLine()) != null)

请告诉我如何模拟这个。 请注意,我无法更改我的主要代码,因此 Mockito 文档中的解决方案对我而言无效

测试代码

@RunWith(PowerMockRunner.class)
@PrepareForTest({ FrameworkUtil.class, LoggerFactory.class })
public class IconPreviewServletTest {
    private IconPreviewServlet iconPreviewServlet;
    private SlingHttpServletRequest request;
    private SlingHttpServletResponse response;
    private Bundle bundle;
    private BundleContext bundleContext;
    private ServiceReference factoryRef;
    private CommonService resolverFactory;
    private PrintWriter out;
    private ResourceResolver resourceResolver;
    private Resource resource;
    private Node node;
    private Node jcrContent;
    private javax.jcr.Property property;
    private Binary binary;
    private InputStream stream;
    private InputStreamReader inputReader;
    private BufferedReader reader;

    @Before
    public void setUp() throws IOException, PathNotFoundException,
            RepositoryException {
        init();
    }

    private void init() throws IOException, PathNotFoundException,
            RepositoryException {

        request = mock(SlingHttpServletRequest.class);
        response = mock(SlingHttpServletResponse.class);
        bundleContext = mock(BundleContext.class);
        factoryRef = mock(ServiceReference.class);
        resolverFactory = mock(CommonService.class);
        out = mock(PrintWriter.class);
        resourceResolver = mock(ResourceResolver.class);
        resource = mock(Resource.class);
        node = mock(Node.class);
        jcrContent = mock(Node.class);
        property = mock(Property.class);
        binary = mock(Binary.class);
        stream=IOUtils.toInputStream("some test data for my input stream");



        reader = mock(BufferedReader.class);

        inputReader=mock(InputStreamReader.class);

        bundle = mock(Bundle.class);
        mockStatic(FrameworkUtil.class);
        mockStatic(LoggerFactory.class);

        Logger log = mock(Logger.class);

        when(LoggerFactory.getLogger(IconPreviewServlet.class)).thenReturn(log);
        when(FrameworkUtil.getBundle(CommonService.class)).thenReturn(bundle);
        when(bundle.getBundleContext()).thenReturn(bundleContext);
        when(bundleContext.getServiceReference(CommonService.class.getName()))
                .thenReturn(factoryRef);
        when(bundleContext.getService(factoryRef)).thenReturn(resolverFactory);
        when(request.getParameter("category")).thenReturn("category");
        when(request.getParameter("query")).thenReturn("query");
        when(response.getWriter()).thenReturn(out);
        when(request.getResourceResolver()).thenReturn(resourceResolver);
        when(
                resourceResolver
                        .getResource("/etc/designs/resmed/icons/category/icons.txt"))
                .thenReturn(resource);
        when(resource.adaptTo(Node.class)).thenReturn(node);
        when(node.getNode("jcr:content")).thenReturn(jcrContent);
        when(jcrContent.getProperty("jcr:data")).thenReturn(property);
        when(property.getBinary()).thenReturn(binary);
        when(binary.getStream()).thenReturn(stream);

    }

最佳答案

要完成这项工作,您需要使用 Powermockito 拦截构造函数调用(new InputStreamReader(...)、new BufferedReader(...)),以便返回您的模拟。下面是一个例子。在您的情况下,只需拦截新的 BufferedReader 调用就足够了。

假设以下是您要测试的代码:

package test;

import java.io.*;

public class SUT {

    public String doSomething() throws IOException {
        InputStreamReader reader =
                new InputStreamReader(getFileAsStream(null, null));
        BufferedReader bReader =
                new BufferedReader(reader);

        return bReader.readLine();
    }

    private InputStream getFileAsStream(Object resourceResolver, Object iconPath)
            throws FileNotFoundException {
        return new ByteArrayInputStream("".getBytes());
    }
}

以下测试代码是如何拦截构造函数调用的示例:

package test;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;

import java.io.BufferedReader;
import java.io.InputStreamReader;

import static org.junit.Assert.assertEquals;
import static org.powermock.api.mockito.PowerMockito.doReturn;
import static org.powermock.api.mockito.PowerMockito.mock;

@RunWith(PowerMockRunner.class)
@PrepareForTest({ SUT.class })
public class SUTTest {

    @Test
    public void doSomethingReturnsValueFromBufferedReader() throws Exception {
        // Arrange
        SUT sut = new SUT();
        InputStreamReader inputStreamReaderMock = mock(InputStreamReader.class);
        BufferedReader bufferedReaderMock = mock(BufferedReader.class);

        // Set your mocks up to be returned when the new ...Reader calls 
        // are executed in sut.doSomething()
        PowerMockito.whenNew(InputStreamReader.class).
                     withAnyArguments().thenReturn(inputStreamReaderMock);
        PowerMockito.whenNew(BufferedReader.class).
                     withArguments(inputStreamReaderMock).
                     thenReturn(bufferedReaderMock);

        // Set the value you want bReader.readLine() to return 
        // when sut.doSomething() executes
        final String bufferedReaderReturnValue = "myValue";
        doReturn(bufferedReaderReturnValue).when(bufferedReaderMock).readLine();

        // Act
        String result = sut.doSomething();

        // Assert
        assertEquals(bufferedReaderReturnValue, result);
    }
}

这有望帮助您解决眼前的问题。然而,在我看来,您正在创建的将是一个非常缓慢、令人困惑和脆弱的测试。现在,您的 mock 太多了,以至于很难确定您实际要测试的是什么。

大量的模拟可能表明您正在测试的代码的设计需要一些工作来提高可测试性。如果您不能触摸代码,那么您就不能 - 但请尝试使您的测试更具可读性和直观性(“当调用此方法时,这件事应该发生,因为......”)。

关于java - 如何使用 mockito 或 powermock 模拟局部变量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20014547/

相关文章:

java - IBM CMOD Java API 在压力条件下失败

c# - 除了使测试更容易之外,封闭系统中的接口(interface)还带来什么优势?

java - Mockito:了解when().thenThrow()函数如何工作

java - 使用Spring Security的Principal进行单元测试方法

java - 使用 JAXB 注释对属性进行分组

java - webapp 内的自定义类加载器、JSP 执行和资源检索

java - JMS - 从一个消费者到多个消费者

objective-c - 在 Swift 单元测试中模拟 Objective-C 代码

java - 使用 Mockito 2 模拟服务导致 stub 错误

java - 如何使用 Mockito 模拟 Java 中的泛型方法?