简体   繁体   English

使用Mockito使用条件循环测试void方法

[英]Test a void method with conditioned loop using mockito

I have following method which asks for user input until valid user credentials are entered.It then generates id for that user and sets registered =TRUE. 我有以下方法要求用户输入,直到输入有效的用户凭据为止,然后为该用户生成ID并设置registered = TRUE。

1.How can I check the value of local variable "registered" from my unit test? 1.如何从单元测试中检查“已注册”局部变量的值?

2.How can I assert in my test that while loop executed until "registered" became TRUE? 2.如何在测试中断言while循环执行到“ registered”变为TRUE为止?

private void register() {

    boolean registered=false;
    while(!registered){
        try {
            String uname =this.read("User Name : ");
            char password[] = this.readPassword();
            String serverURL = this.read("Server URL : ");

            if(!uname.isEmpty() && password!=null && !serverURL.isEmpty()){ 

                registered=this.getUID(uname,password,serverURL);
            }
            if(registered==false)
                System.out.println("\nPlease verify your details and try again!\n");

        } catch (UnsupportedEncodingException e) {} 
        catch(Exception e){}    
    }
    System.out.println("Successful");
}

I have come across usage of ArgumentCaptor to capture variables that a method to be tested, uses to invoke another methods. 我遇到了ArgumentCaptor的用法,以捕获要测试的方法用来调用另一个方法的变量。

e.g verify(mockObj).intArgumentMethod(argument.capture());

However I am not passing variable "registered" to any other method otherwise i would have captured it. 但是,我没有将变量“注册”传递给任何其他方法,否则我会捕获它。

  1. You cannot 你不能
  2. By verification: 通过验证:
    • The loop invariant is that registered is false. 循环不变性是registered为false。 So the loop is not entered if it is true 因此,如果为真,则不会进入循环
    • The loop is exited 循环退出
      • at the bodies start (in this case it is true) 在身体开始的时候(在这种情况下是真的)
      • if a Throwable is thrown, that is not caught by 'catch(Exception e)' (in this case it might be anything) 如果抛出Throwable,则不会被'catch(Exception e)'捕获(在这种情况下,可能是任何东西)

Anyway - review your testing strategy: 无论如何-查看您的测试策略:

  • a function has input parameters and output parameters 一个函数具有输入参数和输出参数
  • the input should be part of the fixture: 输入应该是灯具的一部分:

     this.read("User Name : ") this.readPassword() this.read("Server URL : ") this.getUID(uname,password,serverURL) // this may also be viewed as output 
  • the output should be part of the assertions 输出应该是断言的一部分

     System.out.println(...) 

The input can be set up by creating anonymous sub classes, eg 可以通过创建匿名子类来设置输入,例如

fixture = new YourClass {
  public String read(String prompt) {
    return mockedString;
  }
  ...
};

The output can be captured/asserted by a Junit Rule, eg StandardErrorStreamLog 可以通过Junit规则(例如StandardErrorStreamLog)捕获/声明输出

Mockito is not needed with this example method. 此示例方法不需要Mockito。

Don't test the implementation details, test the behavior given certain input. 不要测试实现细节,在给定输入的情况下测试行为。 If the registered variable is supposed to be some sort of output then it shouldn't be a local variable. 如果该registered变量应该是某种输出,则它不应是局部变量。

One design I like is to use method objects, it is possible to pass arguments at object creation, and an object method can have multiple return values. 我喜欢的一种设计是使用方法对象,可以在创建对象时传递参数,并且对象方法可以具有多个返回值。

class Registrator {
    Registrator(...) { /* assigning needed field */ }

    void register() { /* logic that will mutate internal fields */ }

    boolean registered() { return registered; }
    long triesCount() { return triesCount; }
    // ...
}

And one can adapt the code to use a Report object, on which the register method can append success / failure / more details like reasons / etc. 并且可以修改代码以使用Report对象,在该方法上,register方法可以附加成功/失败/更多详细信息,例如原因/等等。

And the test would be much more easy to write. 而且测试将更容易编写。

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

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