java - 最终类上的 PowerMock UnfinishedStubbingException 错误

标签 java unit-testing junit mockito powermock

尝试让 Mockito 和 PowerMock 正常运行,但在尝试运行此代码时遇到 UnfinishedStubbingException:

@RunWith(PowerMockRunner.class)
@PrepareForTest(FileIOHelper.class)
public class FileIOHelperTest {

    @Test
    public void testIOExceptionOnWrite() {
        PowerMockito.mockStatic(FileIOHelper.class);
        PowerMockito.doThrow(new IOException()).when(FileIOHelper.class);
        PowerMockito.verifyStatic();
        FileIOHelper.write(Mockito.anyString(), Mockito.anyString());
    }

    @After
    public void validate() {
        Mockito.validateMockitoUsage();
    }

}

还有这个 IO 类

public final class FileIOHelper {

    public static void write(final String file, String message, final boolean appendNewLine) {
        if(checkArgs(file, message)) {
            final Path path = Paths.get(file);
            StandardOpenOption mode = StandardOpenOption.APPEND;
            if(Files.notExists(path)) {
                mode = StandardOpenOption.CREATE_NEW;
            }
            if(appendNewLine) {
                message += System.getProperty("line.separator");
            }
            try {
                Files.write(path, message.getBytes(), mode);
            } catch(IOException e) {
                handleException(e, "Problem writing to " + file);
            }
        }
    }

    private static boolean checkArgs(final String... args) {
        if(args != null && args.length > 0) {
            for(final String arg : args) {
                if(arg == null || arg.isEmpty()) {
                    return false;
                }
            }
        }

        return true;
    }

    private static void handleException(final IOException e, final String errorMsg) {
        handleException(e, errorMsg, true);
    }

    private static void handleException(final IOException e, final String errorMsg, final boolean printStace) {
        checkArgs(errorMsg);

        System.err.println(errorMsg);
        System.err.println(e.getMessage());

        if(printStace) {
            e.printStackTrace();
        }
    }

}

我想要做的是以某种方式触发IOException,以便可以测试handleException。为什么有人会问?我正在查看我的 Jacoco 报告,我看到了这一点:

jacoco report

我看过:

我还是完全迷失了。我不知道是否需要触发 IOException 或者是否可以在不使用 doThrow 的情况下验证 handleException 的输出。谁来帮忙啊!

错误日志:

org.mockito.exceptions.misusing.UnfinishedStubbingException: 
Unfinished stubbing detected here:
-> at FileIOHelperTest.testIOExceptionOnWrite(FileIOHelperTest.java:8) // doThrow line

E.g. thenReturn() may be missing.
Examples of correct stubbing:
    when(mock.isOk()).thenReturn(true);
    when(mock.isOk()).thenThrow(exception);
    doThrow(exception).when(mock).someVoidMethod();
Hints:
 1. missing thenReturn()
 2. you are trying to stub a final method, you naughty developer!
 3: you are stubbing the behaviour of another mock inside before 'thenReturn' instruction if completed

最佳答案

我的建议:忘记使用 PowerMock。

如果您必须模拟静态方法,请围绕它构建您自己的小包装类。然后,为了进行测试,您的包装器可以返回控制的内容;以及用于生产用途;你的包装器只调用静态方法。

PowerMock 看起来可以解决很多问题;但迟早它会导致更多问题。它破坏了覆盖范围,使更改底层 JVM 变得更加困难,等等。

说真的:如果您的设计只能使用 PowerMock 进行测试,这通常清楚地表明您的设计糟糕。所以:专注于重新编写被测代码;而不是把时间投入到像 PowerMock 这样弊大于利的工具上。

我花了无数时间试图解决 PowerMock 问题;自从我开始编写“更好地测试”生产代码以来......我已经编写了数百或数千个测试,而不再需要 PowerMock。

就您的情况而言:首先要避免各处静电。基本上,您可以通过(最坏的情况)在必须进行的静态调用周围拉一些包装类来实现这一点。为了进行测试,您可以模拟包装对象;在生产代码中,您使用依赖项注入(inject)来提供一个(单例/枚举)包装器对象,该对象仅进行静态调用。

关于java - 最终类上的 PowerMock UnfinishedStubbingException 错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37291052/

相关文章:

java - @Value 返回 null

unit-testing - 使用 ANTLR 创建的语言的单元/自动测试指南

unit-testing - 如何在 Dart 中对 lib/src 文件进行单元测试?

java - 如何验证使用给定接口(interface)的任何子类型的实例调用的方法

java - 如何在 mockito 测试用例中模拟控制台用户输入

java - 如何将 JSP 变量转换为 Struts2 变量?

java - EE 模块依赖项与构建路径项目

java - 在 JUnit 测试中更改 Spring 实现对象的最佳实践

java - 使用单独的线程更新 JTable

unit-testing - Angular 2——模拟——没有 HTTP 提供者