有 Java 编程相关的问题?

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

java静态模拟不工作

下面是一个模拟java的单元测试示例。尼奥。文件但是这个模拟不起作用,代码试图删除示例路径

@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;
        }
[...]

谢谢


共 (3) 个答案

  1. # 1 楼答案

    我有一个类似的问题,结果是它与准备正确的课程有关

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

    必须将调用静态方法的类添加到@PrepareForTest。。。在我的例子中,这些是不够的,因为访问Files.delete的代码在一个匿名类中,无法显式准备

    我给匿名类命名,并将其添加到@PrepareForTest中,一切正常

  2. # 2 楼答案

    你补充说了吗

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

    到包含该方法的junit测试类

    参见powermock docs,写作测试部分

    编辑:

    嗯,看起来你做的一切都对。以下是我正在运行的:

    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。如果我离开,考试就通过了

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

  3. # 3 楼答案

    我在使用powermock 1.5.1和Files类时遇到了类似的问题,并怀疑它在静态模拟部分/全部jdk1时存在问题。7节课,虽然我不知道为什么。我还检查了javassist版本,当时它是最新的(3.18.0-GA)

    我把测试中的类剥离到文件行,但仍然不起作用。然后我决定尝试模仿另一个静态类StringUtils。斩(“弦”);(commons-lang3)然后我的powermock测试成功了,我能够强制它从mock生成一个异常

    这向我证明了我已经按书做了所有事情,静态模拟在类文件上不起作用,但在StringUtils上起作用

    顺便说一下,我改变了@PrepareForest和PowerMockito。mockStatic()调用以引用正确的类

    最后我放弃了模拟文件。提醒一下,以防其他人也有同样的问题

    编辑。让它工作起来:我在另一个项目中需要它时,又尝试了一次。PowerMock out(1.5.3)有一个更新版本,它使用了一个更新的javassist(3.18.1-GA),修复了我在回复另一条评论时提到的一个bug

    通过将被测试的类添加到@PrepareForTest以及Files现在,即使您正在测试的类没有公开静态方法,我也可以始终让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);
        }
    }