Rob*_*eia 8 java spring unit-testing
我正在尝试为 Spring Boot 中的服务编写一个简单的单元测试。
该服务调用存储库上的方法,该方法返回用户的实例。我正在尝试模拟存储库,因为我只想测试服务。
因此,Repository的代码:
public interface UserRepository extends MongoRepository<User, String> {
User findByEmail(String email);
}
Run Code Online (Sandbox Code Playgroud)
服务接口:
public interface UserService {
@Async
CompletableFuture<User> findByEmail(String email) throws InterruptedException;
}
Run Code Online (Sandbox Code Playgroud)
服务实施:
@Service
public class UserServiceImpl implements UserService {
private UserRepository userRepository;
// dependency injection
// don't need Autowire here
// https://docs.spring.io/spring-boot/docs/current/reference/html/using-boot-spring-beans-and-dependency-injection.html
public UserServiceImpl(UserRepository userRepository) {
this.userRepository = userRepository;
}
@Async
public CompletableFuture<User> findByEmail(String email) throws InterruptedException {
User user = userRepository.findByEmail(email);
return CompletableFuture.completedFuture(user);
}
}
Run Code Online (Sandbox Code Playgroud)
单元测试:
@RunWith(SpringRunner.class)
@SpringBootTest
public class UserServiceTest {
@InjectMocks
UserService userService;
@Mock
UserRepository mockUserRepository;
@Before
public void setUp() {
MockitoAnnotations.initMock(this);
}
@Test
public void mustReturnUser() throws InterruptedException {
String emailTest = "foo@bar.com";
User fakeUser = new User();
fakeUser.setEmail(emailTest);
when(mockUserRepository.findByEmail(emailTest)).thenReturn(fakeUser);
User user = userService.findByEmail(emailTest).join();
assertThat(user).isEqualTo(fakeUser);
verify(mockUserRepository).findByEmail(emailTest);
}
}
Run Code Online (Sandbox Code Playgroud)
当我运行这个测试时,我得到了一个MockitoException:
org.mockito.exceptions.base.MockitoException:
Cannot instantiate @InjectMocks field named 'userService'.
...
Caused by: org.mockito.exceptions.base.MockitoException: the type 'UserService' is an interface.
Run Code Online (Sandbox Code Playgroud)
我没有使用接口,而是尝试使用真正的实现;像这样改变测试:
@InjectMocks
UserServiceImpl userService;
Run Code Online (Sandbox Code Playgroud)
现在,测试成功通过,但这似乎不正确(至少对我而言)。我喜欢测试 Spring Boot 正在使用的 UserService(假设在我的系统的新版本中,我实现了一个新的 UserServicePostgreSQLImpl - 现在我正在使用 MongoDB)。(编辑:请参阅问题中的底部编辑)
我改变了单元测试如下:
@Autowired
@InjectMocks
UserService userService;
Run Code Online (Sandbox Code Playgroud)
但现在我测试失败了:
Expected :model.User@383caf89
Actual :null
Run Code Online (Sandbox Code Playgroud)
出于某种原因,当我使用 时@Autowired,UserRepository模拟不起作用。如果我将 更改为emailTest在我的数据库中使用真实的电子邮件,则测试通过。当我使用时@Autowired,测试使用的是真实版本UserRepository而不是.MockUserRepository
有什么帮助吗?
编辑:查看@msfoster 和@dunni 的答案,并更好地思考,我相信正确的方法是测试每个实现(在我的示例中,使用UserServiceImpl userService)。
为了让你的 UserServiceImpl 在使用 @InjectMocks 注释时自动装配,那么它需要注册为 Spring bean 本身。您可以通过使用 @Service 对 UserServiceImpl 类进行注释来最简单地完成此操作。
这将确保 Spring boot 配置中的组件扫描能够拾取它。(只要扫描包含您的服务类别所在的包!)
| 归档时间: |
|
| 查看次数: |
12746 次 |
| 最近记录: |