有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java在PowerMock中可以对私有静态方法使用部分模拟吗?

PowerMock homepage上的示例中,我看到了以下使用Mockito部分模拟私有方法的示例:

@RunWith(PowerMockRunner.class)
// We prepare PartialMockClass for test because it's final or we need to mock private or static methods
@PrepareForTest(PartialMockClass.class)
public class YourTestCase {
@Test
public void privatePartialMockingWithPowerMock() {        
    PartialMockClass classUnderTest = PowerMockito.spy(new PartialMockClass());

    // use PowerMockito to set up your expectation
    PowerMockito.doReturn(value).when(classUnderTest, "methodToMock", "parameter1");

    // execute your test
    classUnderTest.execute();

    // Use PowerMockito.verify() to verify result
    PowerMockito.verifyPrivate(classUnderTest, times(2)).invoke("methodToMock", "parameter1");
}

然而,当我们希望模拟的私有方法是静态的时,这种方法似乎不起作用。我希望用readFile方法mocked创建以下类的部分模拟:

package org.rich.powermockexample;

import java.io.File;
import java.io.IOException;
import java.nio.charset.Charset;
import java.util.List;

import static com.google.common.io.Files.readLines;

public class DataProvider {

    public static List<String> getData() {
        List<String> data = null;
        try {
            data = readFile();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return data;
    }

    private static List<String> readFile() throws IOException {
        File file = new File("/some/path/to/file");
        List<String> lines = readLines(file, Charset.forName("utf-8"));
        return lines;
    }

}

有人能告诉我如何做到这一点吗


共 (3) 个答案

  1. # 1 楼答案

    测试等级:

    @RunWith(PowerMockRunner.class)
    @PrepareForTest(DataProvider.class)
    public class DataProviderTest {
    
        @Test
        public void testGetDataWithMockedRead() throws Exception {
            mockStaticPartial(DataProvider.class, "readFile");
    
            Method[] methods = MemberMatcher.methods(DataProvider.class, "readFile");
            expectPrivate(DataProvider.class, methods[0]).andReturn(Arrays.asList("ohai", "kthxbye"));
            replay(DataProvider.class);
    
            List<String> theData = DataProvider.getData();
            assertEquals("ohai", theData.get(0));
            assertEquals("kthxbye", theData.get(1));
        }
    
    }
    

    正在测试的类(基本上是您的):

    public class DataProvider {
    
        public static List<String> getData() {
            try {
                return readFile();
            } catch (IOException e) {
                e.printStackTrace();
                return null;
            }
        }
    
        private static List<String> readFile() throws IOException {
            File file = new File("/some/path/to/file");
            return readLines(file, Charset.forName("utf-8"));
        }
    
    }
    
  2. # 2 楼答案

    一般来说,只对您无法控制的类使用静态模拟(例如java.io.File)。因为DataProviderreadFile是你自己的,所以把DataProvider重构成一个合适的类(即使其方法非静态),把readFile拉到一个助手对象中,然后模拟它。看看这个答案

  3. # 3 楼答案

    在做了更多的研究之后,似乎PowerMockito。spy()和PowerMockito。doReturn()是此处所需的:

    package com.richashworth.powermockexample;
    
    import org.junit.Before;
    import org.junit.BeforeClass;
    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.util.ArrayList;
    import java.util.List;
    
    import static org.junit.Assert.assertEquals;
    
    
    @RunWith(PowerMockRunner.class)
    @PrepareForTest({DataProvider.class})
    public class ResultsWriterTest {
    
        private static List<String> mockData = new ArrayList<String>();
        private ResultsWriter resultsWriter;
    
        @BeforeClass
        public static void setUpOnce() {
            final String firstLine = "Line 1";
            final String secondLine = "Line 2";
            mockData.add(firstLine);
            mockData.add(secondLine);
        }
    
        @Before
        public void setUp() {
            resultsWriter = new ResultsWriter();
        }
    
        @Test
        public void testGetDataAsString() throws Exception {
            PowerMockito.spy(DataProvider.class);
            PowerMockito.doReturn(mockData).when(DataProvider.class, "readFile");
    
            final String expectedData = "Line 1\nLine 2\n";
            final String returnedString = resultsWriter.getDataAsString();
    
            assertEquals(expectedData, returnedString);
        }
    
    }
    

    有关更多详细信息和完整的代码列表,请查看我的博客帖子:https://richashworth.com/post/turbocharge-your-mocking-framework-with-powermock/