我试图弄清楚如何编写单元测试,我一度陷入困境:
假设我们有两个测试(视图和服务被模拟):
@Test
public void shouldStartMainActivityWhenUsernameAndPassowordAreCorrect() throws Exception{
when(view.getUsername()).thenReturn("james");
when(view.getPassword()).thenReturn("bond"); //bond
when(serivce.login("james", "bnd")).thenReturn(true); //bnd gives error
presenter.onLoginClicked();
verify(view).startMainActivity();
}
@Test
public void shouldShowErrorMessangeWhenUsernameAndPasswordAreIncorrect() throws Exception{
when(view.getUsername()).thenReturn("james");
when(view.getPassword()).thenReturn("bond"); // bond
when(serivce.login("james", "bnd")).thenReturn(false); // bnd gives no error
presenter.onLoginClicked();
verify(view).showCredentialsError();
}
这是我的演示者方法:
public void onLoginClicked() {
String username = view.getUsername();
if (username.isEmpty()){
view.showUsernameError(R.string.username_error);
return;
}
String password = view.getPassword();
if (password.isEmpty()){
view.showPasswordError(R.string.password_error);
}
boolean loginSucceeded = service.login(username, password);
if (loginSucceeded){
view.startMainActivity();
}else{
view.showCredentialsError();
}
}
怎么来" bnd"硬编码值与" bond"来自另一种方法的硬编码值?
例如:
when(view.getPassword()).thenReturn("bond"); //bond
when(serivce.login("james", "bnd")).thenReturn(true); //bnd
这会给我一个错误,同时将其更改为
when(view.getPassword()).thenReturn("bond"); //bond
when(serivce.login("james", "bond")).thenReturn(true); //bond
没有错误。
答案 0 :(得分:1)
如果登录成功与否,您的服务返回布尔值时,您已经模拟了这两种情况。
您有以下嘲讽:
模拟view.getUsername()
,返回james
。每当从单元测试中在您的测试类上调用此方法时,它将返回此值。
模拟view.getPassword()
,返回bond
。每当从单元测试中在您的测试类上调用此方法时,它将返回此值。
模拟serivce.login()
,其中包含2个参数,即{"username","password"}
,并返回登录状态,即true
或false
。每当使用相同的参数集在您的测试类中调用此方法时,它将返回这些值。
在第一个测试用例中,您将从模拟中返回false
用户名:james
和密码:bnd
,在第二个测试中,您将返回true
同一组参数。
when(serivce.login(" james"," bnd"))。thenReturn(true); // bnd给出 错误
您将在true
返回{"james", "bnd"}
。
when(serivce.login(" james"," bnd"))。thenReturn(false); // bnd不给 错误
您将在false
返回{"james", "bnd"}
。
现在这个模拟器没有在两种情况下执行。这是因为演示者类中的username
和password
始终采用前2个模拟中的值,即view.getUsername()
和view.getPassword()
。这些模拟在两个测试用例中分别返回james
和bonds
。
逻辑上,当且仅当参数为true
而不是其他任何内容时,您应该从测试用例返回false
或{"james","bonds"}
。然后,这将使用其他2个模拟返回的参数进行验证,并根据它们是否完全匹配,将执行第三个模拟并返回布尔值。
积极情景:
when(view.getUsername()).thenReturn("james");
when(view.getPassword()).thenReturn("bond");
when(serivce.login("james", "bond")).thenReturn(true); /* Corrected */
负面情景:
when(view.getUsername()).thenReturn("james");
when(view.getPassword()).thenReturn("bond");
when(serivce.login("james", "bond")).thenReturn(false); /* Corrected */