简体   繁体   English

JUNIT测试void方法

[英]JUNIT testing void methods

I have a java class full of void methods, and I want to make some unit test to get maximal code coverage. 我有一个充满void方法的java类,我想进行一些单元测试以获得最大的代码覆盖率。

For example I have this method : 例如,我有这个方法:

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

Its poorly named for a reason because I translated the code for better understanding. 由于我翻译代码以便更好地理解,因此它的名字很差。 Each methods verify if the arguments are valid in some way and are well written. 每个方法都以某种方式验证参数是否有效并且写得很好。

Example : 示例:

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");
    }
}

My unit test are covering the small methods fine because I ask them to check if the ErrorFile contains the error message, but I dont see how I can test my method checkIfValidElements, it returns nothing or change nothing. 我的单元测试正在覆盖小方法,因为我要求他们检查ErrorFile是否包含错误消息,但我不知道如何测试我的方法checkIfValidElements,它什么都不返回或什么都不改变。 When I run code coverage with Maven, it tells me that the unit test doesent cover this part of my class. 当我使用Maven运行代码覆盖时,它告诉我单元测试会覆盖我课程的这一部分。

The only way I see is to change this method to return an int or bollean value, like this : 我看到的唯一方法是更改​​此方法以返回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;
}

With this method I am able to do an assert equals, but it seems to me that it is futile to do this. 使用这种方法,我能够做一个断言等于,但在我看来这样做是徒劳的。 The problem is that I have a couple of class that are designed like this and its lowering my unit test coverage %. 问题是我有几个类似这样的类,它降低了我的单元测试覆盖率%。

I want to make some unit test to get maximal code coverage 我想进行一些单元测试以获得最大的代码覆盖率

Code coverage should never be the goal of writing unit tests. 代码覆盖率永远不应该是编写单元测试的目标 You should write unit tests to prove that your code is correct, or help you design it better, or help someone else understand what the code is meant to do. 您应该编写单元测试来证明您的代码是正确的,或者帮助您更好地设计它,或者帮助其他人理解代码的意图。

but I dont see how I can test my method checkIfValidElements, it returns nothing or change nothing. 但是我没看到我如何测试我的方法checkIfValidElements,它什么都不返回或什么都没改变。

Well you should probably give a few tests, which between them check that all 7 methods are called appropriately - both with an invalid argument and with a valid argument, checking the results of ErrorFile each time. 那么你应该给它一些测试,它们之间检查所有7个方法都被正确调用 - 无论是有无效参数还是有效参数,每次都检查ErrorFile的结果。

For example, suppose someone removed the call to: 例如,假设某人删除了以下呼叫:

method4(arg1, arg2);

... or accidentally changed the argument order: ...或意外更改了参数顺序:

method4(arg2, arg1);

How would you notice those problems? 你会怎么注意到这些问题? Go from that, and design tests to prove it. 从那里开始,设计测试来证明它。

If your method has no side effects, and doesn't return anything, then it's not doing anything. 如果你的方法没有副作用,并且没有返回任何东西,那么它没有做任何事情。

If your method does some computation and returns the result of that computation, you can obviously enough assert that the result returned is correct. 如果您的方法进行了一些计算并返回该计算的结果,那么显然可以断言返回的结果是正确的。

If your code doesn't return anything but does have side effects, you can call the code and then assert that the correct side effects have happened. 如果您的代码没有返回任何但有副作用,您可以调用代码然后断言正确的副作用已经发生。 What the side effects are will determine how you do the checks. 副作用将决定您如何进行检查。

In your example, you are calling static methods from your non-returning functions, which makes it tricky unless you can inspect that the result of all those static methods are correct. 在您的示例中,您从非返回函数调用静态方法,这使得它很棘手,除非您可以检查所有这些静态方法的结果是否正确。 A better way - from a testing point of view - is to inject actual objects in that you call methods on. 从测试的角度来看,更好的方法是在调用方法时注入实际对象。 You can then use something like EasyMock or Mockito to create a Mock Object in your unit test, and inject the mock object into the class. 然后,您可以使用EasyMock或Mockito之类的东西在单元测试中创建Mock对象,并将模拟对象注入到类中。 The Mock Object then lets you assert that the correct functions were called, with the correct values and in the correct order. 然后,Mock对象允许您断言正确的函数被调用,具有正确的值并且顺序正确。

For example: 例如:

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");
    }
}

Then in your test you can write: 然后在你的测试中你可以写:

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
}

You can still unit test a void method by asserting that it had the appropriate side effect. 您仍然可以通过断言它具有适当的副作用来单元测试void方法。 In your method1 example, your unit test might look something like: 在您的method1示例中,您的单元测试可能类似于:

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

You can learn something called "mocking". 你可以学到一些叫做“嘲弄”的东西。 You can use this, for example, to check if: - a function was called - a function was called x times - a function was called at least x times - a function was called with a specific set of parameters. 例如,您可以使用它来检查: - 函数是否被调用 - 函数被调用x次 - 函数被调用至少x次 - 使用一组特定参数调用函数。 In your case, for example, you can use mocking to check that method3 was called once with whatever you pass as arg1 and arg2. 例如,在您的情况下,您可以使用模拟来检查方法3是否被调用一次,无论您传递的是arg1和arg2。

Have a look at these: https://code.google.com/p/mockito/ https://code.google.com/p/powermock/ 看看这些: https//code.google.com/p/mockito/ https://code.google.com/p/powermock/

I think you should avoid writing side-effecting method. 我认为你应该避免编写副作用方法。 Return true or false from your method and you can check these methods in unit tests. 从您的方法返回true或false,您可以在单元测试中检查这些方法。

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

If it is possible in your case, you could make your methods method1(arg1) ... method7() protected instead of private so they could be accesible from test class within the same package. 如果在您的情况下可以,您可以使方法method1(arg1) ... method7() 受保护而不是私有,因此可以从同一个包中的测试类访问它们。 Then you can simply test all theese methods separately. 然后你可以单独测试所有的theese方法。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM