可以进行合理的单元测试?

时间:2010-04-27 20:41:32

标签: java unit-testing

是否可以为此代码编写合理的单元测试,该代码通过将rar存档委托给主机系统上的有用工具(如果存在)来提取rar存档? 我可以根据我的机器运行linux并安装unrar工具来编写一个测试用例,但是如果另一个运行windows的开发人员检查代码,测试会失败,尽管提取器代码没有任何问题。 我需要找到一种方法来编写一个没有绑定到系统和unrar工具的有意义的测试。 你会如何解决这个问题?

public class Extractor {

private EventBus eventBus;
private ExtractCommand[] linuxExtractCommands = new ExtractCommand[]{new LinuxUnrarCommand()};
private ExtractCommand[] windowsExtractCommands = new ExtractCommand[]{};
private ExtractCommand[] macExtractCommands = new ExtractCommand[]{};

@Inject
public Extractor(EventBus eventBus) {
    this.eventBus = eventBus;
}

public boolean extract(DownloadCandidate downloadCandidate) {
    for (ExtractCommand command : getSystemSpecificExtractCommands()) {
        if (command.extract(downloadCandidate)) {
            eventBus.fireEvent(this, new ExtractCompletedEvent());
            return true;
        }
    }

    eventBus.fireEvent(this, new ExtractFailedEvent());
    return false;
}

private ExtractCommand[] getSystemSpecificExtractCommands() {
    String os = System.getProperty("os.name");
    if (Pattern.compile("linux", Pattern.CASE_INSENSITIVE).matcher(os).find()) {
        return linuxExtractCommands;
    } else if (Pattern.compile("windows", Pattern.CASE_INSENSITIVE).matcher(os).find()) {
        return windowsExtractCommands;
    } else if (Pattern.compile("mac os x", Pattern.CASE_INSENSITIVE).matcher(os).find()) {
        return macExtractCommands;
    }

    return null;
}

}

4 个答案:

答案 0 :(得分:6)

你能否传递一个Map<String,ExtractCommand[]>个实例,然后创建一个抽象方法,比如GetOsName,以获得匹配的字符串。然后你可以在地图中查找匹配字符串,以便在getSystemSpecificExtractCommands方法中获取提取命令。这将允许您注入包含模拟ExtractCommand的列表并覆盖GetOsName方法以返回模拟命令的键,因此您可以在提取工作时测试eventBus被解雇等。

private Map<String,EvenetCommand[]> eventMap;

@Inject
public Extractor(EventBus eventBus, Map<String,EventCommand[]> eventMap) {
    this.eventBus = eventBus;
    this.eventMap = eventMap;
}

private ExtractCommand[] getSystemSpecificExtractCommands() {
    String os = GetOsName();
    return eventMap.Get(os);
}

protected GetOsName();
{
    return System.getProperty("os.name");
}

答案 1 :(得分:1)

我会寻找一些纯java API来操作rar文件。这样代码就不依赖于系统。

谷歌上的快速搜索返回了这个:

http://www.example-code.com/java/rar_unrar.asp

答案 2 :(得分:1)

从模拟框架开始。您需要重构一下,因为如果需要,您需要确保可以覆盖其中一些私有和本地范围属性/变量。

然后,在测试Extract时,确保已经模拟了命令,并确保在模拟对象上调用Extract方法。您还需要确保您的活动也被解雇了。

现在为了使它更易于测试,你可以使用构造函数或属性注入。无论哪种方式,您都需要使私有的ExtractCommand数组可以覆盖。

抱歉,没有时间重新编码和发布,但这应该可以帮助您顺利开始。

祝你好运。

EDIT。如果你想测试它实际上是否被正确提取,那么听起来就像你在功能测试之后更多。

答案 3 :(得分:1)

测试可能很棘手,尤其是在不同类型的测试之间进行划分以及何时应该运行以及他们的职责是什么。使用跨平台代码更是如此。

虽然可以将其视为您正在测试的1个代码库,但它实际上是多个代码库,每个目标平台的通用Java代码和代码,因此您需要进行多次测试。

从单元测试开始,您将不会执行外部命令。相反,每个特定于平台的类都经过测试,以确保它生成正确的命令行,而不实际执行它。

隐藏所有平台细节(要使用的命令)的java类具有单元测试,以验证它是否为给定平台实例化了正确的平台特定类。该平台可以作为核心测试的参数,因此可以“模拟”多个平台。为了进一步进行单元测试,你可以模拟出命令实现(例如,有一个RAR文件,它是未压缩的形式,作为测试数据的一部分,命令是未压缩数据的简单副本。)

一旦这些单元测试到位且为绿色,您就可以继续进行功能测试,执行真正的平台特定命令。当然,这些功能测试必须在实际平台上运行。每个功能测试对应于一个特定于平台的类,它知道如何为unrar创建正确的命令行。

您的构建配置为排除不适用于当前平台的类的测试,例如,因此未在Windows上测试LinuxUnrarer。始终测试平台独立的java类,它将实例化适当的平台特定测试。这为您提供了集成测试,以确保系统端到端地工作。

对于跨平台UNRAR,有一个java RAR scanner,但它没有解压缩。