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



>我有这样的场景

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

我一直嘲笑到现在

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);
    }
}

希望这对您眼前的问题有所帮助。但是,在我看来,您正在创建的将是一个非常缓慢,混乱和脆弱的测试。现在,你嘲笑得太多了,以至于很难确定你实际上在测试什么。

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

使此行正常工作:

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

您必须确定要读取的行数并将其添加到测试代码中:

when(bReader.readLine()).thenReturn("line number one").thenReturn("line number two");

相关内容

  • 没有找到相关文章

最新更新