![](/img/trans.png)
[英]Kotlin Spring Boot testing endpoints and service layer with repository layer mocked
[英]Testing a void service method with mocked repository in Spring Boot?
我的 Spring 引导应用程序提供以下服务,该服务增加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);
}
}
现在我想为此编写一个 JUnit 5 测试,最好是 mocking 存储库,但我想我在这里理解 mocking 的概念有些困难。
如您所见,服务方法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?
}
}
在调用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());
}
}
我建议从方法中返回用户 object 以帮助测试。 要设置模拟存储库行为,请使用Mockito.when
并返回新用户 POJO。 然后在返回的 object 上断言登录失败计数为 1。
您应该只测试您自己的代码,并在单元测试该单元的代码。 因此,例如,如果 Spring 数据存储库save()
有效,则不是。 你可以测试它,但你应该相信它是有效的。
如果做得正确,你应该有一个单元测试断言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
的单元测试(或者它是 MyService?),它断言userIncrementLoginFailures()
和userRepo.save()
是为用户调用 email 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
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.