我正在为我的用户创建操作编写一个测试,其中包括向Kafka发送一条消息。我应该在测试这一部分时嘲笑Kafka吗?最佳实践是什么?
另外,如果我想测试Kafka而不模拟它,它通常在userKafkaProducer中自动连接kafkaTemplate,但当我在测试中运行它时,kafkaTemplate为null。我该怎么办?
@Test
public void testCreateUserSuccess() throws UserNameExistException {
UserRepository userRepo = mock(UserRepository.class);
UserKafkaProducer userKafkaProducer = mock(UserKafkaProducer.class);
UserServiceImpl userService = new UserServiceImpl(userRepo, userKafkaProducer);
UserDTO userDTO = new UserDTO();
userDTO.setUserName("test_user");
when(userRepo.existsByUserName(userDTO.getUserName())).thenReturn(false);
User savedUser = new User();
savedUser.setUserName("test_user");
savedUser.setId("1");
when(userRepo.save(any(User.class))).thenReturn(savedUser);
User user = userService.createUser(userDTO);
assertNotNull(user);
assertNotNull(user.getId());
assertEquals(userDTO.getUserName(), user.getUserName());
verify(userRepo, times(1)).existsByUserName(userDTO.getUserName());
verify(userRepo, times(1)).save(any(User.class));
// Mocking the sendMessage method of UserKafkaProducer
//doNothing().when(userKafkaProducer).sendMessage(any(User.class));
verify(userKafkaProducer, times(1)).sendMessage(user); //mock ?
}
Kafka生产者类
@Service
@AllArgsConstructor
public class UserKafkaProducer {
private final static Logger LOGGER = LoggerFactory.getLogger(UserKafkaProducer.class);
private KafkaTemplate<String, User> kafkaTemplate;
public void sendMessage(User user) {
Message<User> message = MessageBuilder
.withPayload(user)
.setHeader(KafkaHeaders.TOPIC, KafkaTopicConfig.MOVIE_SERVICE_USER_TOPIC_NAME)
.build();
LOGGER.info(String.format("Kafka message sent %s", message));
kafkaTemplate.send(message);
}
}
1条答案
按热度按时间lymgl2op1#
我会说这取决于你试图实现什么类型的测试。
从我所看到的你发布的代码中,看起来你正在尝试编写单元测试。在编写单元测试时,您应该只关注测试“被测单元”,在本例中,它看起来像您的
UserService
类。对于单元服务测试,您通常应该模拟除测试单元和简单数据类之外的几乎所有内容,包括任何模拟的Kafka API。简单地说,你想尽可能地隔离这些东西,这样你就可以专注于测试你的单个单元。Kafka API已经经过严格的测试,您不需要复制它。说了这么多,看看你的代码,KafkaTemplate,在上面的测试中将为null,因为你正在模拟Producer类。在mock中,没有行为,也没有数据,除非您定义它。这对于单元测试来说也不重要,因为该行为现在已经超出了“被测单元”的范围,您只需担心sendMessage函数是否被正确调用。
但是,对于使用
@SpringBootTest
的集成测试(我假设您正在使用上面代码中的SpringBoot),您正在测试多个类的集成和应用程序的流程,我会使用类似@EmbeddedKafka
的东西,它将启动一个临时的本地Kafka供您执行测试,以确保您的Kafka配置正确。这是一篇关于使用@EmbeddedKafka和TestContainers编写Kafka集成测试的好文章:https://www.baeldung.com/spring-boot-kafka-testing
当然,在编写测试时,很多最佳实践都是固执己见的,所以关键是找到一种适合您风险偏好且不会冒犯您同事的方法😅。但我发现,将上述单元测试和集成测试结合起来是实现良好覆盖率和信心的可靠方法。