JUNIT 测试失效方法

2022-08-31 13:49:26

我有一个充满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;
}

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


答案 1

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

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

但是我不明白如何测试我的方法检查IfValidElements,它不返回任何内容或更改任何内容。

好吧,您可能应该给出一些测试,这些测试在它们之间检查是否正确调用了所有7种方法 - 使用无效参数和有效参数,检查每次的结果。ErrorFile

例如,假设有人删除了对以下各项的调用:

method4(arg1, arg2);

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

method4(arg2, arg1);

您如何注意到这些问题?从那里开始,并设计测试来证明这一点。


答案 2

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

如果您的方法执行一些计算并返回该计算的结果,则显然可以断言返回的结果是正确的。

如果您的代码没有返回任何内容,但确实有副作用,则可以调用代码,然后断言发生了正确的副作用。副作用是什么将决定您如何进行检查。

在示例中,您正在从不返回的函数调用静态方法,除非您能够检查所有这些静态方法的结果是否正确,否则这使其变得棘手。从测试的角度来看,一种更好的方法是注入实际对象,以便调用方法。然后,您可以使用 EasyMock 或 Mockito 之类的东西在单元测试中创建一个 Mock 对象,并将该 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
}

推荐