如何使用Mockito或Powermock模拟局部变量 [英] How to mock local variables using mockito or powermock

查看:1442
本文介绍了如何使用Mockito或Powermock模拟局部变量的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有这样的情况

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

直到现在我一直在嘲笑

getFileAsStream(resourceResolver, iconpath)

现在我有一位读者

 BufferedReader bReader = new BufferedReader(reader);

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

but when I execute this line I get null and not able to move forward

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

请告诉我我该如何嘲笑. 请注意,我无法更改我的主要代码,因此在我的情况下,Mockito文档中提供的解决方案无效

Please tell me how can I mock this. Please note I cannot change my main code therefore the solution present on Mockito docs is not valid in my case

测试代码

@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调用就足够了.

To make this work, you need to use Powermockito to intercept the constructor calls (new InputStreamReader(...), new BufferedReader(...)) so that your mocks get returned. An example is below. In your case, just intercepting the new BufferedReader call may be enough.

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

Assume the following is the code you want to test:

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

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

The following test code is an example of how to intercept the constructor calls:

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

这有望帮助您解决眼前的问题.但是,在我看来,您所创建的内容将是一个非常缓慢,令人困惑且脆弱的测试.现在,您正在嘲笑太多,以致于很难确定您实际要测试的内容.

This hopefully helps you in your immediate problem. However, it seems to me that what you're creating will be a very slow, confusing and brittle test. Right now, you're mocking so much that it makes very hard to determine what you're actually trying to test.

大量的模拟可能表明您正在测试的代码设计需要一些工作来提高可测试性.如果您无法触摸代码,那么您将无法这样做-但请尝试使您的测试更具可读性和直观性(调用此方法时,应该会发生这种情况,因为...").

The high amount of mocking probably indicates that the design of the code you're testing would need some work to improve testability. If you can't touch the code, then you can't - but try to make your test more readable and intuitive ("When this method is invoked, this thing should happen, because...").

这篇关于如何使用Mockito或Powermock模拟局部变量的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆