为什么测试中的某些硬编码值会影响其他人?

时间:2016-02-06 06:48:03

标签: java android junit mocking

我试图弄清楚如何编写单元测试,我一度陷入困境:

假设我们有两个测试(视图和服务被模拟):

@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

没有错误。

1 个答案:

答案 0 :(得分:1)

如果登录成功与否,您的服务返回布尔值时,您已经模拟了这两种情况。

您有以下嘲讽:

  1. 模拟view.getUsername(),返回james。每当从单元测试中在您的测试类上调用此方法时,它将返回此值。

  2. 模拟view.getPassword(),返回bond。每当从单元测试中在您的测试类上调用此方法时,它将返回此值。

  3. 模拟serivce.login(),其中包含2个参数,即{"username","password"},并返回登录状态,即truefalse。每当使用相同的参数集在您的测试类中调用此方法时,它将返回这些值。

  4. 在第一个测试用例中,您将从模拟中返回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"}

    现在这个模拟器没有在两种情况下执行。这是因为演示者类中的usernamepassword始终采用前2个模拟中的值,即view.getUsername()view.getPassword()。这些模拟在两个测试用例中分别返回jamesbonds

    逻辑上,当且仅当参数为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 */