是否可以使用预定义的 arraylist 作为 db 模拟身份验证?

Is it possible to mock authentication with predefined arraylist as db?

我正在学习 mock,我想知道我是否可以使用类似这样的代码:

Mockito.when(service.authenticateUser(test)).thenReturn(any());

验证身份验证是否成功。

service.AuthenticateUser(用户用户):

@Override
public Player authenticateUser(User login) throws AuthenticationException {
    Player find = new Player();

    for (Player player : initializedPlayers) {
            if (login.getEmail().equals(player.getEmail()) && login.getPassword().equals(player.getPassword())) {

            loggedPlayer = player;
            return player;
            }
    }
    throw new AuthenticationException("Incorrect email and/or password");
}

如您所见,login 方法 returns 一个 Player,但是有没有可能的方法告诉 Mockito 我只想取回一些东西,如果它有效?这样我就可以测试认证是否成功,例如:

Mockito.when(service.authenticateUser(test)).thenReturn(any(Player.class));
    assertNotNull(service.authenticateUser(test));

^此方法目前无效,它给出了对存根的失败测试。

编辑:我尝试以两种不同的方式解决这个问题:

@Test
public void testFailAuthWithMockedService(){
    DefaultSportsBettingService service = mock(DefaultSportsBettingService.class);
    User test = new User("test","test");
    Mockito.when(service.authenticateUser(test)).thenReturn(any(Player.class));
    assertNotNull(service.authenticateUser(test));
}
@Test
public void testSuccessfulAuthWithMockedService(){
    DefaultSportsBettingService service = mock(DefaultSportsBettingService.class);
    User test = new User("validName","validPassword");
    Mockito.when(service.authenticateUser(test)).thenReturn(any());
    assertNotNull(service.authenticateUser(test));
}

这些代码符合要求,但我不确定它们是否真的好。

附加信息: 最开始在我的main中调用了这个方法:

 @Override
public Player authenticateUser(User login) throws AuthenticationException {
    Player find = new Player();

    for (Player player : initializedPlayers) {
            if (login.getEmail().equals(player.getEmail()) && login.getPassword().equals(player.getPassword())) {

            loggedPlayer = player;
            return player;
            }
    }
    throw new AuthenticationException("Incorrect email and/or password");
}

main():(使用身份验证的主体部分)

 while(true) {
        try {
            dsbs.authenticateUser(view.readCredentials());
            if(dsbs.getLoggedPlayer() != null){
                break;
            }


        } catch (AuthenticationException ae) {
            ae.printStackTrace();
        }
    }
Mockito.when(service.authenticateUser(test)).thenReturn(any(Player.class));
assertNotNull(service.authenticateUser(test));

通过模拟 service.authenticateUser(test) 的 return 值,您正在测试 Mockito,而不是您自己的代码。

is there a possible way to tell Mockito that I only want to get something back, if its valid? So I would be able to test wheter the authentication was succesful or not

不要为此使用 Mockito。相反,您需要创建一个 initializedPlayers 列表并使其可用于 authenticateUser() 函数。理想情况下,当您在测试中创建它时,您可以将此列表传递给 service 对象的构造函数。如果没有,那么你必须以 service 需要的时候得到他们的方式创建球员。

同样,您可以创建一个测试来验证 authenticateUser () 在给定用户不在玩家列表中时抛出 AuthenticationException

您不能在 thenReturn 语句中使用 any(...),这就是错误的来源。

此代码应该有效:

Mockito.when(service.authenticateUser(test)).thenReturn(new Player(...));
assertNotNull(service.authenticateUser(test));

现在如果你想根据登录的值存根不同的结果,你可以在 when() 部分使用 argumentMatchers:

Mockito.when(service.authenticateUser(any(User.class))
  .thenThrow(AuthenticationException.class);
Mockito.when(service.authenticateUser(argThat(login -> list.contains(login))
  .thenReturn(new Player(...));

assertNotNull(service.authenticateUser(test));

这里的顺序很重要:Mockito 将尝试以与存根相反的顺序匹配您的参数,因此在这里它将首先检查登录名是否在给定列表中,如果该存根失败,它将回退到第一个存根,它将为其他任何事情抛出 AuthenticationException。

如果您希望返回的Player 依赖于登录用户,您可以使用.thenAnswer() 而不是.thenReturn()。参见 Mockito : doAnswer Vs thenReturn