首页 > 解决方案 > JUnit - 如何对读取目录中的文件并使用外部库的方法进行单元测试

问题描述

我在 NetBeans 插件中使用了这个方法:

public static SourceCodeFile getCurrentlyOpenedFile() {
        MainProjectManager mainProjectManager = new MainProjectManager();
        Project openedProject = mainProjectManager.getMainProject();

        /* Get Java file currently displaying in the IDE if there is an opened project */
        if (openedProject != null) {
            TopComponent activeTC = TopComponent.getRegistry().getActivated();
            DataObject dataLookup = activeTC.getLookup().lookup(DataObject.class);
            File file = FileUtil.toFile(dataLookup.getPrimaryFile());                   // Currently opened file

            // Check if the opened file is a Java file
            if (FilenameUtils.getExtension(file.getAbsoluteFile().getAbsolutePath()).equalsIgnoreCase("java")) {
                return new SourceCodeFile(file);
            } else {
                return null;
            }

        } else {
            return null;
        }
    }

基本上,使用 NetBeans API,它检测用户当前在 IDE 中打开的文件。然后,它加载它并从中创建一个SourceCodeFile对象。

现在我想使用 JUnit 对这个方法进行单元测试。问题是我不知道如何测试它。

由于它没有接收任何参数作为参数,因此我无法测试在给定错误参数的情况下它的行为方式。我还考虑过尝试操作openedProject以测试给定该对象的一些不同值的方法行为,但就我而言,我不能以这种方式操作 JUnit 中的变量。我也无法检查该方法返回什么,因为单元测试将始终返回 null,因为它没有检测到 NetBeans 中打开的任何文件。

所以,我的问题是:我该如何处理这种方法的单元测试?

标签: javaunit-testingjunitjunit4

解决方案


好吧,您的方法确实采用“字里行间”的参数:

MainProjectManager mainProjectManager = new MainProjectManager();
Project openedProject = mainProjectManager.getMainProject();

基本上获取要处理的对象。

因此,第一步是将该方法签名更改为:

public static SourceCodeFile getCurrentlyOpenedFile(Project project) {
...

当然,除了那个空检查之外,没有使用那个对象。所以下一个级别将是有一个独特的方法,比如

SourceCodeFile lookup(DataObject dataLookup) {

换句话说:您真正的问题是您编写了难以测试的代码。“默认”答案是:您必须更改生产代码,以便更容易测试。

例如,将其拆分,并将所有不同的方面放入较小的辅助方法中。

你看,最后一个方法lookup(),那个方法接受一个参数,现在(不知何故)有可能为此考虑测试用例。您可能必须使用 Mockito 等模拟框架在测试代码中传递该DataObject类的模拟实例。

长话短说:这里没有弯路。您无法(以合理的方式)测试您的代码,因为它目前是结构化的。重新构建你的生产代码,然后你所有关于“当我通过 X,然后 Y 应该发生”的想法都可以解决。

免责声明:是的,理论上,您可以通过严重依赖 PowerMock(ito) 或 JMockit 等框架来测试上述代码。这些框架允许您控制(模拟)对静态方法的调用,或对new(). 所以他们会让你完全控制你方法中的一切。但这基本上会迫使您的测试了解被测方法中发生的一切。这是一件非常糟糕的事情。


推荐阅读