静态模拟不起作用

Sta*_*art 6 java junit static mockito powermock

我有以下示例单元测试,试图模拟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));
    }
Run Code Online (Sandbox Code Playgroud)

知道什么是错的吗?

这是方法的内容 visitor.postVisitDirectory

[...]
if (e == null) {
            Files.delete(dir);
            return FileVisitResult.CONTINUE;
        }
[...]
Run Code Online (Sandbox Code Playgroud)

谢谢,

Tom*_*sky 5

你添加了吗

@RunWith(PowerMockRunner.class)
@PrepareForTest(Files.class)
Run Code Online (Sandbox Code Playgroud)

到包含该方法的 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));
  }
}
Run Code Online (Sandbox Code Playgroud)

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

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


Mat*_*rne 5

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

我将正在测试的班级剥离到“文件”行,但仍无法正常工作。然后,我决定尝试模拟另一个静态类StringUtils.chop(“ string”);。(commons-lang3),然后我的powermock测试成功了,我能够强制它从模拟生成异常。

这向我证明了我完成了本书的所有工作,并且静态模拟在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);
    }
}
Run Code Online (Sandbox Code Playgroud)

和下面的测试:

@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);
    }
}
Run Code Online (Sandbox Code Playgroud)