我试图了解如何在 Spring 项目中使用 Mockito ,但是我对以下内容有些困惑:
我将要使用真实的(内存中的)存储库测试服务。我在嘲笑该服务正在使用的所有其他对象。如果我理解正确,将模拟使用 @Mock 注释对象,使用 @Spy 使用真实对象以及使用 @InjectMocks 这些注释对象的“自动装配”。但是,我认为我误会了 @Spy ,因为以下代码无法正常工作(似乎插入了模拟对象,似乎没有db交互,也没有出现NullPointerException):
@SpringBootTest
@RunWith(SpringRunner.class)
public class UserServiceTests {
@Spy
@Autowired
private UserRepository userRepository;
@Mock
private MessageService messageService;
@InjectMocks
private UserService userService = new UserServiceImpl();
@Test
public void testUserRegistration() {
userService.registerUser("test@test.test");
Assert.assertEquals("There is one user in the repository after the first registration.", 1, userRepository.count());
}
}
如果我删除 @Spy 批注,并使用反射将存储库插入服务中,那么它将起作用:
ReflectionTestUtils.setField(userService, "userRepository", userRepository);
这似乎很不方便,我很确定 @Spy 可以做到这一点。谁能指出我的缺失/误解?
编辑:还有一件事情-使用 @Spy 批注,保存时我没有得到NullPointerException,但似乎插入了一个模拟对象,而不是真正的对象。存储库。
编辑2:我认为这是我困惑的答案:
答案 0 :(得分:1)
问题在于您可能@Autowire UserService中的某些服务/存储库 像这样:
public class UserServiceImpl() {
@Autowired
private UserRepository userRepository;
@Autowired
private MessageService messageService;
// ... all the stuff
}
Mockito尝试通过不可用的构造函数或setter注入模拟。 尝试重新设计类UserServiceImpl,使其具有类似以下的构造函数:
public class UserServiceImpl() {
private final UserRepository userRepository;
private final MessageService messageService;
@Autowired
public UserServiceImpl(UserRepository userRepository, MessageService messageService) {
this.userRepository = userRepository;
this.messageService = messageService;
}
比起您可以使用构造函数使用这些模拟实例化@Before中的服务。