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

JUnit - How to unit test method that reads files in a directory and uses external libraries

我在 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 中的变量。我也无法检查方法 returns,因为单元测试总是 return null,因为它没有检测到 NetBeans 中任何打开的文件。

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

嗯,你的方法确实有参数,"between the lines":

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

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

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

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

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

SourceCodeFile lookup(DataObject dataLookup) {

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

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

你看,最后一个方法 lookup(),它接受一个参数,现在(以某种方式)可以为此设计测试用例。可能您将不得不使用 Mockito 等模拟框架在您的测试代码中传递该 DataObject class 的 mocked 实例。

长话短说:这里没有弯路。您不能(以合理的方式)测试您的代码,因为它当前是结构化的。重新构建您的生产代码,然后您所有关于 "when I pass X, then Y should happen" 的想法都可以实现。

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