6

我有以下示例单元测试,它试图模拟 java.nio.file.Files 但这个模拟不起作用并且代码试图删除示例路径。

@Test
    public void testPostVisitDirectory() throws Exception {
        Path mockedPath = Paths.get("sample path");
        PowerMockito.mockStatic(Files.class);
        PowerMockito.doNothing().when(Files.class,
                PowerMockito.method(Files.class, "delete", Path.class));

        DeleteDirVisitor visitor = new DeleteDirVisitor(false);
        Assert.assertEquals("The was a problem visiting the file",
                FileVisitResult.CONTINUE,
                visitor.postVisitDirectory(mockedPath, null));
    }

知道有什么问题吗?

这是方法的内容visitor.postVisitDirectory

[...]
if (e == null) {
            Files.delete(dir);
            return FileVisitResult.CONTINUE;
        }
[...]

谢谢,

4

3 回答 3

5

我在使用 powermock 1.5.1 和 Files 类时遇到了类似的问题,并且怀疑它在静态模拟一些/所有 jdk1.7 类时存在问题,尽管我不知道为什么。我还检查了 javassist 版本,当时它是最新的(3.18.0-GA),

我将我的测试类剥离到 Files 行,但它仍然不起作用。然后我决定尝试模拟另一个静态类 StringUtils.chop("string"); (commons-lang3) 然后我的 powermock 测试工作了,我能够强制它从 mock 中生成异常。

这向我证明了我已经按照书本完成了所有工作,并且静态模拟在 Files 类上不起作用,但在 StringUtils 上起作用。

顺便说一句,我更改了 @PrepareForTest 和 PowerMockito.mockStatic() 调用以引用正确的类。

最后我放弃了嘲笑文件。只是提醒一下,以防其他人遇到同样的问题。

编辑。得到它的工作:我已经再次尝试了这个,因为我在另一个项目中需要它。有一个更新版本的 PowerMock out (1.5.3) 使用更新的 javassist (3.18.1-GA) 修复了我在回复另一条评论时提到的错误。

即使您正在测试的类没有公开静态方法,我也可以Files通过将被测类添加到现在和现在@PrepareForTest一样来不断地模拟工作。Files对于其他静态模拟,我以前不需要这样做。我不知道为什么需要它或对Files.

例子:

public class MyTestClass {

    public void justToTestMocking(Path path) throws IOException {
        if (!Files.exists(path)) {
            throw new IllegalArgumentException("I know there is a deleteIfExists() but I am just testing mocking");
        }
        Files.delete(path);
    }
}

以及下面的测试:

@RunWith(PowerMockRunner.class)
@PrepareForTest({Files.class, MyTestClass.class})
public class MyTestClassTest {

    @Before
    public void setUp() {
        mockStatic(Files.class);

    }        

    @Test
    public void justToTestMocking_WillDeletePath() throws IOException {
        Path path = mock(Path.class);
        MyTestClass test = new MyTestClass();

        when(Files.exists(path)).thenReturn(true);

        test.justToTestMocking(path);

        verifyStatic();
        Files.delete(path);
    }
}
于 2013-07-11T06:03:15.993 回答
4

你加了吗

@RunWith(PowerMockRunner.class)
@PrepareForTest(Files.class)

到包含该方法的junit测试类?

请参阅powermock 文档,写作测试部分。

编辑:

嗯,看来你做的一切都是对的。这是我正在运行的内容:

import java.io.IOException;
import java.nio.file.FileVisitResult;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.SimpleFileVisitor;

import org.junit.Assert;
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;

@RunWith(PowerMockRunner.class)
@PrepareForTest(Files.class)
public class TestVisitor {
  public class PrintingVisitor extends SimpleFileVisitor<Path> {
    @Override
    public FileVisitResult postVisitDirectory(final Path dir, final IOException exc) throws IOException {
      Files.delete(dir);
      return FileVisitResult.CONTINUE;
    }
  }

  @Test
  public void testPostVisitDirectory() throws Exception {
    final Path mockedPath = Paths.get("sample path");

    /* Mocking */
    PowerMockito.mockStatic(Files.class);
    PowerMockito.doNothing().when(Files.class, PowerMockito.method(Files.class, "delete", Path.class));
    /* End Mocking */

    final PrintingVisitor visitor = new PrintingVisitor();
    Assert.assertEquals("The was a problem visiting the file", FileVisitResult.CONTINUE, visitor.postVisitDirectory(mockedPath, null));
  }
}

如果我注释掉标记为 Mocking 的部分,我会得到NoSuchFileException. 如果我离开它,测试通过。

也许发布产生错误的完整示例?

于 2013-02-19T20:57:05.657 回答
1

我有一个类似的问题,事实证明它与准备正确的课程有关。

在上面的示例中,被测试的类已经在“prepareFor-Scope”中,因为它是测试类的内部类。

您必须将类添加到@PrepareForTest调用静态方法...在我的情况下,这些还不够,因为访问的代码Files.delete位于无法显式准备的匿名类中。

我命名了匿名类并将其添加到@PrepareForTest并且一切正常

于 2013-07-05T08:36:48.020 回答