JUNIT测试void方法

时间:2013-04-16 17:55:44

标签: java junit

我有一个充满void方法的java类,我想进行一些单元测试以获得最大的代码覆盖率。

例如我有这个方法:

protected static void checkifValidElements(int arg1,  int arg2) {
    method1(arg1);
    method2(arg1);
    method3(arg1, arg2);
    method4(arg1, arg2);
    method5(arg1);
    method6(arg2);
    method7();
}

由于我翻译代码以便更好地理解,因此其命名不佳。每个方法都以某种方式验证参数是否有效并且写得很好。

示例:

private static void method1(arg1) {
    if (arg1.indexOf("$") == -1) {

        //Add an error message 
        ErrorFile.errorMessages.add("There is a dollar sign in the specified parameter");
    }
}

我的单元测试正在覆盖小方法,因为我要求他们检查ErrorFile是否包含错误消息,但是我没有看到我如何测试我的方法checkIfValidElements,它什么都不返回或什么也没有改变。当我使用Maven运行代码覆盖时,它告诉我单元测试会覆盖我班级的这一部分。

我看到的唯一方法是更改​​此方法以返回int或bollean值,如下所示:

protected static int checkifValidElements(int arg1,  int arg2) {
    method1(arg1);
    method2(arg1);
    method3(arg1, arg2);
    method4(arg1, arg2);
    method5(arg1);
    method6(arg2);
    method7();
    return 0;
}

使用这种方法我可以做一个断言等于,但在我看来这样做是徒劳的。问题是我有几个类似这样的类,它降低了我的单元测试覆盖率%。

7 个答案:

答案 0 :(得分:55)

  

我想进行一些单元测试以获得最大的代码覆盖率

代码覆盖率绝不应该是编写单元测试的目标。您应该编写单元测试来证明您的代码是正确的,或者帮助您更好地设计它,或者帮助其他人理解代码的用途。

  

但是我没看到我如何测试我的方法checkIfValidElements,它什么都不返回或什么也没有改变。

那么你应该给出一些测试,它们之间检查所有7个方法都被正确调用 - 无论是参数无效还是有效参数,每次检查ErrorFile的结果。

例如,假设有人将呼叫移除到:

method4(arg1, arg2);

...或意外更改了参数顺序:

method4(arg2, arg1);

您如何看待这些问题?从那里开始,设计测试来证明它。

答案 1 :(得分:21)

如果你的方法没有副作用,并且没有返回任何东西,那么它没有做任何事情。

如果你的方法做了一些计算并返回了那个计算的结果,你显然可以断言返回的结果是正确的。

如果你的代码没有返回任何东西,但有副作用,你可以调用代码,然后断言正确的副作用已经发生。副作用将决定你如何进行检查。

在您的示例中,您从非返回函数调用静态方法,这使得它很棘手,除非您可以检查所有这些静态方法的结果是否正确。从测试的角度来看,更好的方法是在调用方法时注入实际对象。然后,您可以使用EasyMock或Mockito之类的东西在单元测试中创建Mock对象,并将模拟对象注入到类中。然后Mock对象允许您断言正确的函数被调用,具有正确的值并且顺序正确。

例如:

private ErrorFile errorFile;

public void setErrorFile(ErrorFile errorFile) {
    this.errorFile = errorFile;
}

private void method1(arg1) {
    if (arg1.indexOf("$") == -1) {

        //Add an error message 
        errorFile.addErrorMessage("There is a dollar sign in the specified parameter");
    }
}

然后在你的测试中你可以写:

public void testMethod1() {
    ErrorFile errorFile = EasyMock.createMock(ErrorFile.class);
    errorFile.addErrorMessage("There is a dollar sign in the specified parameter");
    EasyMock.expectLastCall(errorFile);
    EasyMock.replay(errorFile);

    ClassToTest classToTest = new ClassToTest();
    classToTest.setErrorFile(errorFile);
    classToTest.method1("a$b");

    EasyMock.verify(errorFile); // This will fail the test if the required addErrorMessage call didn't happen
}

答案 2 :(得分:4)

您仍然可以通过声明它具有适当的副作用来对void方法进行单元测试。在您的method1示例中,您的单元测试可能类似于:

public void checkIfValidElementsWithDollarSign() {
    checkIfValidElement("$",19);
    assert ErrorFile.errorMessages.contains("There is a dollar sign in the specified parameter");
}

答案 3 :(得分:2)

我认为你应该避免编写副作用方法。从您的方法返回true或false,您可以在单元测试中检查这些方法。

答案 4 :(得分:2)

你可以学到一些叫做“嘲笑”的东西。例如,您可以使用它来检查是否:   - 调用了一个函数   - 一个函数被称为x次   - 一个函数被调用至少x次   - 使用一组特定参数调用函数。 例如,在您的情况下,您可以使用模拟来检查方法3是否被调用一次,无论您传递给arg1和arg2。

看看这些: https://code.google.com/p/mockito/ https://code.google.com/p/powermock/

答案 5 :(得分:1)

如果您的方法无效并且想要检查异常,则可以使用expectedhttps://weblogs.java.net/blog/johnsmart/archive/2009/09/27/testing-exceptions-junit-47

答案 6 :(得分:0)

如果您的情况有可能,您可以将方法method1(arg1) ... method7() 保护而不是私有,这样他们就可以可以从同一个包中的测试类访问。然后你可以单独测试所有的theese方法。