使用 mockito 测试带有条件循环的 void 方法
Test a void method with conditioned loop using mockito
我有以下方法要求用户输入,直到有效的用户凭据为 entered.It,然后为该用户生成 ID 并设置已注册 =TRUE。
1.How 我可以从我的单元测试中检查局部变量 "registered" 的值吗?
2.How 我可以在我的测试中断言 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());
但是我没有将变量 "registered" 传递给任何其他方法,否则我会捕获它。
- 你不能
- 通过验证:
- 循环不变量是
registered
为假。所以如果为真则不进入循环
- 循环退出
- 在身体开始时(在这种情况下是正确的)
- 如果抛出一个 Throwable,它不会被 'catch(Exception e)' 捕获(在这种情况下它可能是任何东西)
无论如何 - 检查您的测试策略:
- 一个函数有输入参数和输出参数
输入应该是夹具的一部分:
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 规则,输出可以是 captured/asserted,例如StandardErrorStreamLog
此示例方法不需要 Mockito。
不要测试实施细节,测试给定特定输入的行为。如果 registered
变量应该是某种输出,那么它不应该是局部变量。
我喜欢的一种设计是使用方法对象,可以在对象创建时传递参数,一个对象方法可以有多个return值。
class Registrator {
Registrator(...) { /* assigning needed field */ }
void register() { /* logic that will mutate internal fields */ }
boolean registered() { return registered; }
long triesCount() { return triesCount; }
// ...
}
并且可以调整代码以使用 Report
对象,注册方法可以在该对象上附加成功/失败/更多详细信息,例如原因等。
而且测试会更容易编写。
我有以下方法要求用户输入,直到有效的用户凭据为 entered.It,然后为该用户生成 ID 并设置已注册 =TRUE。
1.How 我可以从我的单元测试中检查局部变量 "registered" 的值吗?
2.How 我可以在我的测试中断言 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());
但是我没有将变量 "registered" 传递给任何其他方法,否则我会捕获它。
- 你不能
- 通过验证:
- 循环不变量是
registered
为假。所以如果为真则不进入循环 - 循环退出
- 在身体开始时(在这种情况下是正确的)
- 如果抛出一个 Throwable,它不会被 'catch(Exception e)' 捕获(在这种情况下它可能是任何东西)
- 循环不变量是
无论如何 - 检查您的测试策略:
- 一个函数有输入参数和输出参数
输入应该是夹具的一部分:
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 规则,输出可以是 captured/asserted,例如StandardErrorStreamLog
此示例方法不需要 Mockito。
不要测试实施细节,测试给定特定输入的行为。如果 registered
变量应该是某种输出,那么它不应该是局部变量。
我喜欢的一种设计是使用方法对象,可以在对象创建时传递参数,一个对象方法可以有多个return值。
class Registrator {
Registrator(...) { /* assigning needed field */ }
void register() { /* logic that will mutate internal fields */ }
boolean registered() { return registered; }
long triesCount() { return triesCount; }
// ...
}
并且可以调整代码以使用 Report
对象,注册方法可以在该对象上附加成功/失败/更多详细信息,例如原因等。
而且测试会更容易编写。