JUnit-如何单元测试方法,该方法读取目录中的文件并使用外部库

时间:2018-08-23 14:20:22

标签: java unit-testing junit junit4

我有在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中任何打开的文件。

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

1 个答案:

答案 0 :(得分:3)

好吧,您的方法确实采用了“在行之间”的参数:

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

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

所以第一步就是将方法签名更改为:

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

当然,除了该空检查之外,不使用该对象。因此, next 级别将具有类似的方法

SourceCodeFile lookup(DataObject dataLookup) {

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

例如,将其撕开,然后将所有不同的方面放入较小的辅助方法中。

您会看到,最后一个方法lookup()带有一个参数,现在(某种程度上)可以为此考虑测试用例了。可能必须使用Mockito之类的模拟框架才能在测试代码中传递该DataObject类的 mocked 实例。

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

免责声明:是的,从理论上讲,您可以通过严重依赖PowerMock(ito)或JMockit等框架来测试上述代码。这些框架允许您 contol (模拟)对静态方法或new()的调用。因此,它们将使您完全控制方法中的所有内容。但这基本上会迫使您的测试了解被测方法中正在发生的所有事情。这真是一件坏事。