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

标签 java android junit mocking

我正在尝试弄清楚如何编写单元测试,但我卡在了一点:

假设我们有两个测试(模拟了 View 和服务):

@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

没有报错。

最佳答案

当您的服务返回一个 boolean 值表示登录是否成功时,您已经模拟了这两种情况。

您有以下模拟:

  1. 模拟 view.getUsername() 返回 james。每当从单元测试中对测试类调用此方法时,它都会返回此值。

  2. 模拟 view.getPassword() 返回 bond。每当从单元测试中对测试类调用此方法时,它都会返回此值。

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

在第一个测试用例中,您从用户名 james 和密码:bnd 的 mock 中返回 false,在第二个测试中,您为同一组参数返回 true

when(serivce.login("james", "bnd")).thenReturn(true); //bnd gives error

在这里,您为 {"james", "bnd"} 返回 true

when(serivce.login("james", "bnd")).thenReturn(false); // bnd gives no error

在这里,您为 {"james", "bnd"} 返回了 false

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

从逻辑上讲,当且仅当参数是 {"james","bonds"} 时,您应该从测试用例中返回 truefalse 而不是其他任何东西。然后将使用其他 2 个模拟返回的参数对其进行验证,并根据它们是否完全匹配,将执行第三个模拟并返回 boolean 值。

积极的情景:

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 */

关于java - 为什么测试中的某些硬编码值会影响其他值?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35238242/

相关文章:

java - 缓冲写入器现在正在写入文件

使用 document.location.href = ="slide"时,jquery 移动数据转换 ""不起作用;已插入 href =""

java - 如何使用 Mockito 测试 sendEmail() 方法而不发送电子邮件?

java - 寻找免费且简单的(自动)生成 JUnit 测试的方法

java - 如何在 WebView Android 中加载 url 时显示进度条

java - 使用 jar 构建 java 项目到一个 jar 中(命令行)

java - TreeModel 中的内部类的属性不可读

android - 如何通过链接(而不是复制)使应用程序使用其自身文件夹之外的模块?

Android ImageView 的可绘制色调不起作用

java - 如何使用isA-Matcher