How to mock local variables using mockito or powermock

后端 未结 2 866
醉话见心
醉话见心 2020-12-16 05:51

I have scenario like this

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


        
相关标签:
2条回答
  • 2020-12-16 06:48

    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...").

    0 讨论(0)
  • 2020-12-16 06:48

    to make this line work:

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

    you must determine how many lines you want to read and add this to your test code:

    when(bReader.readLine()).thenReturn("line number one").thenReturn("line number two");
    
    0 讨论(0)
提交回复
热议问题