javaspringbootmockito@injectmock说明如何仅模拟选定的依赖项
我有一个名为@Service
的UserServiceImpl
依赖于另外两个bean。一个是UserRepository
bean,另一个是名为SessionService
的bean
我的要求是在测试UserServiceImpl类期间,我必须能够注入SessionService
依赖项的模拟,但保持UserRepository
依赖项的原样
我的服务类如下所示:
@Service
@Slf4j
public class UserServiceImpl implements UserService {
@Autowired
private UserRepository userRepository;
@Autowired
private SessionService sessionService;
@Override
public User create(User user) {
log.info("User Creation at Service");
// ... Do some validations .. //
// This needs to be mocked in Unit Tests
String returnValue = sessionService.doSomethingThatIDontWantInTests();
user.setInternalKey(returnValue);
// .. Do some more Validations .. //
return userRepository.save(user);
}
}
现在,这是我的测试课:
@SpringBootTest
class UserServiceTest {
@InjectMocks
private UserServiceImpl userService;
@Mock
private SessionService sessionService;
@Test
void CreateUserTest() {
Mockito.when(sessionService.doSomethingThatIDontWantInTests()).thenReturn("abcxyz123321");
User user = new User();
user.setName("John Doe");
user.setEmail("john.doe@example.com");
User savedUser = userService.create(user);
assertNotNull(savedUser.getUserId());
}
}
当我运行这个测试时,Mockito成功地模拟了SessionService
调用。但是,UserServiceImpl.createUser()
仍然失败,消息说:
java.lang.NullPointerException: Cannot invoke "com.myproject.data.repos.UserRepository.save(User)" because "this.userRepository" is null
我是否应该将UserRepository
也作为mock注入,并使用Mockito来模拟UserRepository.save()
方法
我只想模拟SessionService
依赖项,而不是UserRepository
依赖项
这是可行的吗?如果是,怎么做?请告知
谢谢, 斯利拉姆
# 1 楼答案
您必须使用
@SpyBean
(https://docs.spring.io/spring-boot/docs/current/api/org/springframework/boot/test/mock/mockito/SpyBean.html),它将注入原始bean,但您可以验证调用和参数# 2 楼答案
你正在混合不同的测试风格
Style 1-spring集成测试
此时,Spring Boot在其上下文中创建bean,并将它们注入测试类
@SpringBootTest
@Autowired
将bean注入测试@MockBean
将Spring上下文中的bean替换为mock风格2-单元测试
这不使用Spring DI。在这种风格中,模拟所有依赖项是典型的
@ExtendWith(MockitoExtension.class)
@Mock
@InjectMocks
注释SUT使用真正的依赖关系也是可能的,但在这种情况下,您需要手动构造SUT-Mockito不支持部分注入
单元测试往往更加轻量级,不那么脆弱,另一方面,集成测试覆盖了应用程序的很大一部分
请注意,如果
UserRepository
是spring数据repo,则不能手动创建它