有没有办法使用JUnit5和Mockito检查是否使用了局部变量方法?

huangapple go评论77阅读模式
英文:

Is there a way to check if local variable methods have been used with JUnit5 and Mockito?

问题

我有一个用于用户实体的服务类。其中一个方法负责更改用户密码。这里出现了问题。该方法在数据库中查找用户并将其存储在一个局部变量中。显然,它在运行,但有没有办法编写一个测试来检查用户类中的密码设置方法是否被使用?

我已经为这个问题寻找了半天的解决方案,但我只找到了一个值得质疑的解决方案,它使用了Powermock库。然而,自从去年以来,这个库没有更新过。

没有使用Mockito.verify()或类似的东西的可能性,因为它在外部不可见。

对于这样的情况编写测试是否有意义?
英文:

I've got a service class for the User entity. One of the methods is responsible for changing the user password. And here is the problem. The method looks for a user in the database and stores it in a local variable. Obviously, it's working, but is there a way to write a test to check if the password setter method in the user class was used?

public AuthenticationResponse changeUserPassword(ChangeUserPasswordDto changeUserPasswordDto,
            String jwtToken)
            throws RuntimeException
{
        User user = userRepository.findByEmail(jwtUtil.extractUsername(jwtToken)).get();

        if (!passwordEncoder.matches(changeUserPasswordDto.getPassword(),user.getPassword()))
            throw new InvalidPasswordException("Old password is not matching.");
        if (!changeUserPasswordDto.getNewPassword().equals(changeUserPasswordDto.getNewPasswordConfirmation()))
            throw new NotMatchingPasswordsException("Passwords are not matching.");

        user.setPassword(passwordEncoder.encode(changeUserPasswordDto.getNewPassword()));
        user.setLastCredentialsChangeTime(System.currentTimeMillis());
        return AuthenticationResponse.builder().token(jwtUtil.generateToken(userRepository.save(user))).build();
}

I've been looking for a solution to this problem for half of the day, but I found only one questionable solution using Powermock library. Still, this library hasn't been updated since last year.

There is no possibility of using Mockito.verify() or something because it's not visible outside.

Does it even make sense to write a test for something like this?

答案1

得分: 0

以下是您要翻译的部分:

  1. 使用从模拟存储库返回的对象的 getter 方法来验证密码是否已更改是我认为最简单的两种方法之一。它是相同的对象实例,因此如果在测试方法内部进行修改,我们可以在测试方法调用后看到:
@Test
void userWithGetter() {
    var email = "email@example.com";
    var password = "admin123";
    var user = new User();
    when(userRepository.findByEmail(email))
            .thenReturn(Optional.of(user));

    testedClass.changeUserPassword(email, password);

    assertEquals(password, user.getPassword());
}
  1. 类似地,但如果 User 类没有密码的 getter,我们可以对从模拟存储库返回的对象进行监视以验证 setter 的调用:
@Test
void userWithoutGetter() {
    var email = "email@example.com";
    var password = "admin123";
    var user = spy(new User());
    when(userRepository.findByEmail(email))
            .thenReturn(Optional.of(user));

    testedClass.changeUserPassword(email, password);

    verify(user).setPassword(password);
}

我已经理解您的要求,将代码部分保持原样,只提供翻译的内容。如果需要任何进一步的澄清,我将乐意提供帮助。

英文:

Two simplest ways of verifying if the password was changed are in my opinion:

  1. Using a getter of the object returned from the mocked repository. It's the same object instance, so if it's modified inside the tested method, we can see that after the method is called in the test:
@Test
void userWithGetter() {
    var email = "email@example.com";
    var password = "admin123";
    var user = new User();
    when(userRepository.findByEmail(email))
            .thenReturn(Optional.of(user));

    testedClass.changeUserPassword(email, password);

    assertEquals(password, user.getPassword());
}
  1. Similarly, but in case User class does not have a getter for the password, we can spy on the object that we're returning from the mocked repository to verify the setter call:
@Test
void userWithoutGetter() {
    var email = "email@example.com";
    var password = "admin123";
    var user = spy(new User());
    when(userRepository.findByEmail(email))
            .thenReturn(Optional.of(user));

    testedClass.changeUserPassword(email, password);

    verify(user).setPassword(password);
}

I've prepared a GitHub repository with shortened code reproducing your class under test and included the tests described above - both pass. If any further clarification is needed, I'd be happy to help.

huangapple
  • 本文由 发表于 2023年6月29日 02:03:06
  • 转载请务必保留本文链接:https://go.coder-hub.com/76575677.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定