Java - 单元测试

5

在一个Java类中给定以下方法:

public void execute(String command) {

    ProcessBuilder processBuilder = new ProcessBuilder(command);
    Process process = processBuilder.start();

    int exitValue = process.waitFor();
    if (exitValue != 0) {
        throw new RuntimeException("a message here...");
    }
}

我正在尝试为这个方法设计一个适当的跨平台单元测试。

我正在寻找一个所有操作系统(Win,Linux,Mac等)都通用的命令或者是一个可以在我的单元测试中传递给该方法的虚假命令。

有什么建议吗?


1
我认为如果您可以在所有平台上运行junit,那么您就可以使用简单的主类运行Java命令。 - andy
你的方法返回类型为 void;如果它返回 exitValue,可能会有所帮助。 - S.L. Barth
5
如果进程返回非成功的退出值,该方法会抛出异常,因此返回退出值将是无意义的,因为始终会返回0。 - Alderath
2个回答

8

这种方法不能通过单元测试进行测试,只能通过集成测试进行测试。如果要进行单元测试,可以进行小的重构。引入一个新的接口ProcessBuilderFactory(以及默认实现),并将其注入到您的类中。

public interface ProcessBuilderFactory {
    ProcessBuilder createProcessBuilder(String command);
}

public class DefaultProcessBuilderFactory implements ProcessBuilderFactory {
    public ProcessBuilder createProcessBuilder(String command) {
        return new ProcessBuilder(command);
    }
}

public class ProcessExecutor {
    private ProcessBuilderFactory processBuilderFactory;
    private ProcessExecutor(ProcessBuilderFactory processBuilderFactory) {
        this.processBuilderFactory = processBuilderFactory;
    }

    public void execute(String command) {
        ProcessBuilder processBuilder = processBuilderFactory.createProcessBuilder(command);
        Process process = processBuilder.start();

        int exitValue = process.waitFor();
        if (exitValue != 0) {
            throw new RuntimeException("a message here...");
        }
    }
}

然后你可以通过注入模拟 ProcessBuilderFactory 来创建一个 单元测试

在编写测试时,你创建一个模拟的 ProcessBuilderFactory,返回一个模拟的 ProcessBuilder…该死,ProcessBuilder 也是 final 的 :(

强烈提醒:先编写测试!

所以我们有两个选择:

  1. 引入一个新的接口来包装 ProcessBuilder,并提供默认实现…就像我们创建 ProcessBuilderFactory 一样
  2. 撤消重构,并查看 PowerMock,用于模拟 final 类

1
实际上,该测试将简单地测试进程是否被调用并正确处理。另一个单元测试应该测试ProcessBuilder创建的进程的正确性。 - dstibbe
我相信你无法对ProcessBuilderFactory进行单元测试,原因与你无法对原始方法进行单元测试相同。 - Dušan Rychnovský
顺便说一下,ProcessBuilder本身是一个FINAL类,我无法继承它。所以我需要引入另一个接口,比如MyProcessBuilder,它有一个默认实现,是对java ProcessBuilder的包装。听起来这对于一个单元测试来说有点繁琐 :) - mhshams

2

由于这是Java单元测试,您可以使用java.exe作为标准exe。例如,运行java.exe -version命令。它将始终存在:)。使用来自java.home的当前jdk,然后使用该jdk引用java.exe。

针对特定要求,您可以使用任何模拟框架吗?(例如jmockit


2
嗯,有了.exe,它就不是真正的跨平台了,对吧 :)?此外,这也假设Java已经在路径中,但并非总是如此。 - jqno
从你的问题中,我认为你需要一个在所有测试环境中输出一些信息的命令。我认为你在所有测试环境中都有Java。你可以随时找到java.exe并使用绝对路径。 - Jayan
2
我的意思是,在Linux和OS X上,该文件不会被称为java.exe;这只适用于Windows。OP明确要求跨平台的东西。 - jqno

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接