如何让PowerMock从静态方法返回期望值



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

private final static String pathToUUID = "path/to/my/file.txt";
public String getUuid () throws Exception {
    return new String(Files.readAllBytes(Paths.get(pathToUUID)));;
}

UUID存储在应用程序首次运行时创建的文件中。CCD_ 1存在于由CCD_ 2指示的位置中。我正在为这个方法写一个单元测试。

@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()模式正常工作呢?

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

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

您需要测试的类的编写方式很糟糕。路径不应该是硬编码的——使其可参数化——例如,通过构造函数注入路径。然后,在集成测试中,只需注入测试资源的路径,就可以开始了。没有PowerMock,没有黑客——简单的构造函数注入。

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

这是IMHO,更好,因为:

  • 没有powermock:这是一个强大的工具,但它有价格(较慢的测试,可能的测试奇怪的交互
  • 它更可读/更容易理解

相关内容

  • 没有找到相关文章

最新更新