java—在SpringBoot中用模拟存储库测试一个void服务方法?

mtb9vblg  于 2021-07-24  发布在  Java
关注(0)|答案(3)|浏览(306)

我的springboot应用程序提供以下服务,它在 User 实体并将其持久化到数据库。

@Service
public class MyService {

    @Autowired
    UserRepo userRepo;

    public void incrementLoginFailures(String email) throws UserNotFoundException {
        final User user = userRepo.findByEmail(email).orElseThrow(UserNotFoundException::new);
        user.incrementLoginFailures();
        userRepo.save(user);
    }
}

现在我想为此编写一个junit5测试,更喜欢模拟respository,但我想我在理解模拟的概念时遇到了一些困难。
如您所见,服务方法 incrementLoginFailures() 不返回任何内容,所以我不知道如何检查 User 实体实际上是递增的。我需要为这种检查编写一个集成测试吗?这种检查实际上会启动一个数据库?

@ExtendWith(MockitoExtension.class)
public class UserServiceTest {

  @InjectMocks
  private UserService userService;

  @Mock
  private UserRepo userRepo;

  @Test
  public void shouldIncrement() {
    userService.incrementLoginFailures("foo@bar.com");
    Assertions.assertEquals(1, xyz);  // from what source would xyz come from?
  }
}
dgsult0t

dgsult0t1#

您应该只测试自己的代码,并在单元中测试该单元的代码。例如,如果spring数据存储库 save() 作品。你可以测试它,但你应该相信它是有效的。
如果做得正确,您应该有一个单元测试来Assert user.incrementLoginFailures() 一切正常。

// Unit test for the user
@Test
public void shouldIncrement() {
    User user = new User();
    // In here when you have just initialized user you might know that 
    // the initial count is zero but it is overall better to assert 
    // the logic for any value / case
    int originalLoginFailures = user.getLoginFailures();
    user.incrementLoginFailures();
    assertEquals(originalLoginFailures + 1, user.getLoginFailures());
 }

除了数据保存到数据库之外,这实际上是您需要知道的。
所以你可能有一个单元测试 UserService (或者是我的服务?) userIncrementLoginFailures() 以及 userRepo.save() 为电子邮件用户调用foo@bar.com 什么时候 userService.incrementLoginFailures("foo@bar.com") 被称为。
那就由我来做 verify ,例如:

@InjectMocks
private MyService userService;
@Mock
private UserRepo userRepo;
@Mock
private User user; 

@Test
public void shouldIncrementAndSave() throws UserNotFoundException {
    when(userRepo.findByEmail("foo@bar.com")).thenReturn(Optional.of(user));
    userService.incrementLoginFailures("foo@bar.com");
    verify(user).incrementLoginFailures();
    verify(userRepo).save(user);
}

你可以测试一下 user.incrementLoginFailures() 在这里也可以工作,但是因为您在用户单元测试中测试了它,所以不一定需要它,但是它是一个冗余测试,并且测试一个不属于单元测试的逻辑,即 UserService .

fkaflof6

fkaflof62#

在调用之前在测试方法中 userService.incrementLoginFailures("foo@bar.com"); 您需要模拟对userrepo调用的方法的返回值,如下所示:

@ExtendWith(MockitoExtension.class)
public class UserServiceTest {

  @InjectMocks
  private UserService userService;

  @Mock
  private UserRepo userRepo;

  @Test
  public void shouldIncrement() {
    User user = new User();//please initialize as per your requirement
    when(userRepo.findByEmail("foo@bar.com")).thenReturn(user);
    userService.incrementLoginFailures("foo@bar.com");//this method will make changes to the user object
    Assertions.assertEquals(1, user.getLoginFailures());
  }
}
ff29svar

ff29svar3#

我建议从方法返回user对象以帮助测试。要设置模拟存储库行为,请使用 Mockito.when 并返回一个新用户pojo。然后在返回的对象上Assert登录失败计数为1。

相关问题