【问题标题】:How Can I Get PowerMock to Return the Expected Value from a Static Method如何让 PowerMock 从静态方法返回预期值
【发布时间】:2016-05-05 20:11:18
【问题描述】:

考虑我需要测试的类中的以下字段和方法。

private final static String pathToUUID = "path/to/my/file.txt";

public String getUuid () throws Exception {
    return new String(Files.readAllBytes(Paths.get(pathToUUID)));;
}

UUID 存储在应用程序首次运行时创建的文件中。 file.txt 存在于pathToUUID 指示的位置。我正在尝试(并且正在努力)为此方法编写单元测试。

@RunWith(PowerMockRunner.class)
@PrepareForTest({Files.class})
public class MyTest {

    private final String expected = "19dcd640-0da7-4b1a-9048-1575ee9c5e39";

    @Test
    public void testGetUuid() throws Exception {
        UUIDGetter getter = new UUIDGetter();
        PowerMockito.mockStatic(Files.class);
         when(Files.readAllBytes(any(Path.class)).thenReturn(expected.getBytes());
        String retrieved = getter.getUuid();
        Assert.assertEquals(expectedUUID, retrieved);
    }
}

不幸的是,when().thenReturn() 在测试期间没有被调用,并且测试作为集成测试执行,从文件系统读取文件并返回它的值,而不是我期望的模拟值。但是,如果我在测试方法中欺骗了对Files.readAllBytes() 的调用并将结果回显到控制台,则会显示expected 值。

那么,我怎样才能让我的测试方法与 PowerMock when()-thenReturn() 模式一起正常运行?

【问题讨论】:

    标签: java junit mockito powermock


    【解决方案1】:

    对于任何面临类似问题的人,我通过对我的测试类进行以下更改来解决这个问题:

    @RunWith(PowerMockRunner.class)
    @PrepareForTest({UUIDStasher.class})
    public class TestUUIDStasher {
    
        private final String expectedUUID = "19dcd640-0da7-4b1a-9048-1575ee9c5e39";
        Path spoofPath = Paths.get("C:\\DIRECTORY");
    
        @Before
        public void setup() throws Exception {
            MockitoAnnotations.initMocks(this);
            PowerMockito.mockStatic(Paths.class);
            PowerMockito.mockStatic(Files.class);
            when(Paths.get(any(String.class))).thenReturn(spoofPath);
            when(Files.readAllBytes(any(Path.class))).thenReturn(expectedUUID.getBytes());
        }
    
        @Test
        public void testGetUUID() throws Exception {
            UUIDStasher stasher = new UUIDStasher();
            String retrieved = stasher.getUuid();
            Assert.assertEquals(expectedUUID, retrieved);
        }
    }
    

    【讨论】:

      【解决方案2】:

      您需要测试的课程写得不好。路径不应被硬编码 - 使其可参数化 - 例如通过构造函数注入路径。然后,在您的集成测试中,只需注入测试资源的路径,您就可以开始了。没有 PowerMock,没有 hack - 简单的构造函数注入。

      【讨论】:

        【解决方案3】:

        JDK 类在使用 PowerMock 时很难处理。在你的情况下,我会这样做:

        重构 UUIDGetter 以添加一个用于测试目的的构造函数,该构造函数接受“uuid”文件的路径:

        package so37059406;
        
        import java.nio.file.Files;
        import java.nio.file.Paths;
        
        public class UUIDGetter {
        
            private final static String PATH_TO_UUID = "path/to/my/file.txt";
        
            private final String path;
        
            public UUIDGetter() {
                this(PATH_TO_UUID);
            }
        
            // for testing purposes
            protected UUIDGetter(final String path) {
                this.path = path;
            }
        
            public String getUuid() throws Exception {
                return new String(Files.readAllBytes(Paths.get(this.path)));
            }
        }
        

        然后像这样测试它:

        package so37059406;
        
        import org.junit.Test;
        
        import static org.junit.Assert.assertEquals;
        
        public class UUIDGetterTest {
            @Test
            public void testGetUuid() throws Exception {
                final UUIDGetter getter = new UUIDGetter(getClass().getClassLoader().getResource("so37059406/uuid.txt").getPath());
                assertEquals("19dcd640-0da7-4b1a-9048-1575ee9c5e39", getter.getUuid());
            }
        }
        

        使用名为“so37059406/uuid.txt”并包含(无行尾)的资源文件(在测试资源文件夹中):

        19dcd640-0da7-4b1a-9048-1575ee9c5e39
        

        这是恕我直言,更好,因为:

        • 没有 powermock:它是一个功能强大的工具,但需要付出一定的代价(测试速度较慢,可能测试奇怪的交互
        • 更具可读性/易于理解

        【讨论】:

          猜你喜欢
          • 2012-03-24
          • 1970-01-01
          • 1970-01-01
          • 2018-05-23
          • 1970-01-01
          • 2016-09-20
          • 2013-06-09
          • 1970-01-01
          相关资源
          最近更新 更多