Spring Boot Mockito - @InjectMocks - 如何仅模拟选定的依赖项

Sri*_*ran 1 java unit-testing mockito spring-boot

我有一个依赖于另外两个 bean 的@Service调用。UserServiceImpl一个是UserRepositorybean,另一个是名为 的 bean SessionService

我的要求是在 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);
    }
}
Run Code Online (Sandbox Code Playgroud)

现在,这是我的测试类:

@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());

    }
}
Run Code Online (Sandbox Code Playgroud)

当我运行此测试时,Mockito 成功模拟了SessionService调用。但是,UserServiceImpl.createUser()仍然失败,并显示消息:

java.lang.NullPointerException: Cannot invoke "com.myproject.data.repos.UserRepository.save(User)" because "this.userRepository" is null
Run Code Online (Sandbox Code Playgroud)

我应该UserRepository也作为模拟注入并使用 Mockito 来模拟该UserRepository.save()方法吗?

我只想模拟SessionService依赖关系,而不是UserRepository依赖关系。

这是可行的吗?如果是这样,怎么办?请指教。

谢谢,斯里拉姆

Les*_*iak 7

您正在混合不同的测试风格。

样式1-spring集成测试

此时 Spring Boot 在其上下文中创建 bean,并将它们注入到测试类中。

  • 使用@SpringBootTest
  • 用于@Autowired将 beans 注入到您的测试中
  • 用于@MockBean通过模拟替换 Spring 上下文中的 bean

样式 2 - 单元测试

这不使用 Spring DI。在这种风格中,通常会模拟所有依赖项。

  • 使用@ExtendWith(MockitoExtension.class)
  • 将依赖项注释为@Mock
  • 注释SUT@InjectMocks

使用真正的依赖项也是可能的,但在这种情况下,您需要手动构建 SUT - Mockito 不支持部分注入。

单元测试往往更加轻量级且不易损坏,另一方面集成测试覆盖了应用程序的很大一部分。

请注意,如果UserRepository是 spring-data 存储库,则无法手动创建它。