使用mockito测试带有条件循环的void方法

时间:2015-03-11 18:31:24

标签: java unit-testing junit mocking mockito

我有以下方法要求用户输入,直到输入有效的用户凭据。然后为该用户生成id并设置registered = TRUE。

1.如何从单元测试中检查“已注册”的局部变量的值?

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

我遇到过使用ArgumentCaptor来捕获要测试的方法的变量,用于调用其他方法。

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

但是我没有将变量“注册”传递给任何其他方法,否则我会捕获它。

2 个答案:

答案 0 :(得分:1)

  1. 你不能
  2. 通过验证:
    • 循环不变量是registered为假。因此,如果确实存在,则不输入循环
    • 退出循环
      • 在身体开始(在这种情况下是真的)
      • 如果抛出一个Throwable,那就不会被抓住(例外e)' (在这种情况下,它可能是任何东西)
  3. 无论如何 - 请检查您的测试策略:

    • 一个函数有输入参数和输出参数
    • 输入应该是灯具的一部分:

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

      System.out.println(...)
      

    可以通过创建匿名子类来设置输入,例如

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

    输出可以由Junit规则捕获/断言,例如StandardErrorStreamLog

    此示例方法不需要Mockito。

答案 1 :(得分:0)

不测试实现细节,测试给定某些输入的行为。如果registered变量应该是某种输出,则它不应该是局部变量。

我喜欢的一个设计是使用方法对象,可以在创建对象时传递参数,而对象方法可以有多个返回值。

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

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

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

可以调整代码以使用Report对象,注册方法可以在其上附加成功/失败/更多细节,例如原因/等。

测试会更容易编写。