java - 使用 mockito 为 findById() JPA 方法编写 Junit 测试用例时,我收到错误 java.util.NoSuchElementException: No value present
问题描述
由于 JPA 的 findById 方法的返回类型是可选的,并且我使用 get 方法来获取确切的值,因此我无法实现单元测试。
我的服务代码:
公共类 LobbyService {
private final Logger log = LoggerFactory.getLogger(LobbyService.class);
private final LobbyRepository lobbyRepository;
private final UserRepository userRepository;
@Autowired
public LobbyService(@Qualifier("lobbyRepository") LobbyRepository lobbyRepository, @Qualifier("userRepository") UserRepository userRepository) {
this.lobbyRepository = lobbyRepository;
this.userRepository = userRepository;
}
public Lobby createLobby(Lobby newLobby){
checkIfLobbyExist(newLobby);
lobbyRepository.save(newLobby);
return newLobby;
}
public void updateStatusOfLobby(long id, int status){
Lobby lobby = getLobby(id);
lobby.setStatus(status);
saveOrUpdate(lobby);
}
public void saveOrUpdate(Lobby updateLobby){
lobbyRepository.save(updateLobby);
}
public List<LobbyGetDTO> getAllLobbies(){
List<Lobby> lobbyList = this.lobbyRepository.findAll();
List<LobbyGetDTO> lobbyGetDTOList = new ArrayList<>();
for(Lobby tempLobby:lobbyList){
LobbyGetDTO lobbyGetDTO = DTOMapper.INSTANCE.convertEntityToLobbyGetDTO(tempLobby);
lobbyGetDTOList.add(lobbyGetDTO);
}
return lobbyGetDTOList;
}
public void removePlayerFromLobby(long id, long userId){
Lobby lobby = getLobby(id);
String baseErrorMessage = "This player id is invalid. Please provide proper id";
if(lobby.getPlayerIds().contains(userId)){
lobby.getPlayerIds().remove(userId);
}
else{
throw new LobbyException(baseErrorMessage);
}
saveOrUpdate(lobby);
}
public void addPlayerToLobby(long id, long userId){
Lobby lobby = getLobby(id);
if(lobby.getStatus()==1){
throw new LobbyException("Game is in progress. You can't join lobby in the middle of the game. Please try later");
}
//Checking if the user exists before adding the user to lobby
userRepository.findById(userId)
.orElseThrow(
() -> new LobbyException(String.format("User with id: %d doesn't exist", userId))
);
String baseErrorMessage = "The lobby cannot have more than 7 player. Please join different lobby";
//Size of lobby is limited to maximum of 7 players.
if(lobby.getPlayerIds().size()>=7){
throw new LobbyException(baseErrorMessage);
}
//Player should be unique in the lobby
if(lobby.getPlayerIds().contains(userId)){
baseErrorMessage = "Player already exists in the lobby";
throw new LobbyException(baseErrorMessage);
}
lobby.getPlayerIds().add(userId);
saveOrUpdate(lobby);
}
public Lobby getLobby(Long id){
Lobby lobby = this.lobbyRepository.findById(id).get();
String baseErrorMessage = "The lobby %d doesn't exist. Please check the lobby which you are joining";
if(null == lobby){
throw new LobbyException(baseErrorMessage);
}
return lobby;
}
public void checkIfLobbyExist(Lobby lobbyToBeCreated) {
/*
This method checks the uniqueness of the lobby by lobby name. If the lobby with the same name
exists then it should not be created.
*/
Lobby newLobby = lobbyRepository.findByName(lobbyToBeCreated.getName());
String baseErrorMessage = "The provided %s is not unique. Therefore, the lobby could not be created!";
if (null != newLobby) {
throw new LobbyException(String.format(baseErrorMessage, "lobby name"));
}
}
}
我的 Junit 代码:
public class LobbyServiceTest {
@Mock
LobbyRepository lobbyRepository;
@Mock
UserRepository userRepository;
@InjectMocks
LobbyService lobbyService;
private User testUser;
private Lobby lobbyTest;
@BeforeEach
public void setupLobby(){
MockitoAnnotations.initMocks(this);
lobbyTest = new Lobby();
lobbyTest.setName("testLobby");
lobbyTest.setHostPlayerId(1L);
testUser = new User();
testUser.setId(1L);
testUser.setName("testName");
testUser.setUsername("testUsername");
// when -> any object is being save in the userRepository -> return the dummy testUser
Mockito.when(userRepository.save(Mockito.any())).thenReturn(testUser);
Mockito.when(lobbyRepository.save(Mockito.any())).thenReturn(lobbyTest);
}
@Test
public void createdLobby_validInputs_success(){
Lobby createdLobby = lobbyService.createLobby(lobbyTest);
Mockito.verify(lobbyRepository, Mockito.times(1)).save(Mockito.any());
assertEquals(createdLobby.getId(),lobbyTest.getId());
assertEquals(createdLobby.getName(),lobbyTest.getName());
assertEquals(createdLobby.getHostPlayerId(),lobbyTest.getHostPlayerId());
}
@Test
public void createdLobbyExist_Exception(){
lobbyService.createLobby(lobbyTest);
Mockito.when(lobbyRepository.findByName(Mockito.any())).thenReturn(lobbyTest);
assertThrows(LobbyException.class, ()->lobbyService.createLobby(lobbyTest));
}
@Test
public void addUserToLobbyWhenGameGoingOn(){
lobbyTest.setStatus(1);
lobbyService.createLobby(lobbyTest);
Mockito.when(lobbyRepository.findById(Mockito.any())).thenReturn(java.util.Optional.ofNullable(lobbyTest));
assertThrows(LobbyException.class,()->lobbyService.addPlayerToLobby(1L,1L));
}
@Test
public void addUserToLobby(){
List<Long> playerList = new ArrayList<>();
Long[] longList = new Long[]{2L,3L,4L,5L,6L,7L};
Collections.addAll(playerList,longList);
lobbyTest.setPlayerIds(playerList);
lobbyService.createLobby(lobbyTest);
//Mockito.when(lobbyRepository.getOne(anyLong())).thenReturn(lobbyTest);
Mockito.when(lobbyRepository.findById(anyLong())).thenReturn(lobbyTest);
Mockito.when(userRepository.findById(1L)).thenReturn(java.util.Optional.ofNullable(testUser));
Mockito.when(lobbyRepository.save(Mockito.any(Lobby.class))).thenReturn(lobbyTest);
lobbyService.addPlayerToLobby(1L,1L);
assertEquals(lobbyTest.getPlayerIds().size(),7);
}
@Test
public void addExistingUserToLobby(){
List<Long> playerList = new ArrayList<>();
Long[] longList = new Long[]{1L,3L,4L,5L,6L,7L};
Collections.addAll(playerList,longList);
lobbyTest.setPlayerIds(playerList);
lobbyService.createLobby(lobbyTest);
//Mockito.when(lobbyRepository.getOne(anyLong())).thenReturn(lobbyTest);
Mockito.when(lobbyRepository.findById(anyLong())).thenReturn(lobbyTest);
Mockito.when(userRepository.findById(1L)).thenReturn(Optional.ofNullable(testUser));
Mockito.when(lobbyRepository.save(Mockito.any(Lobby.class))).thenReturn(lobbyTest);
assertThrows(LobbyException.class,()->lobbyService.addPlayerToLobby(1L,1L));
}
@Test
public void addMoreThanSevenPlayerToLobby(){
List<Long> playerList = new ArrayList<>();
Long[] longList = new Long[]{1L,2L,3L,4L,5L,6L,7L};
Collections.addAll(playerList,longList);
lobbyTest.setPlayerIds(playerList);
lobbyService.createLobby(lobbyTest);
//Mockito.when(lobbyRepository.getOne(anyLong())).thenReturn(lobbyTest);
Mockito.when(lobbyRepository.findById(anyLong())).thenReturn(lobbyTest);
Mockito.when(userRepository.findById(1L)).thenReturn(Optional.ofNullable(testUser));
Mockito.when(lobbyRepository.save(Mockito.any(Lobby.class))).thenReturn(lobbyTest);
assertThrows(LobbyException.class,()->lobbyService.addPlayerToLobby(1L,8L));
}
}
错误信息:
No value present
java.util.NoSuchElementException: No value present
at java.base/java.util.Optional.get(Optional.java:148)
我不想将 findById 的返回类型更改为 Optional。在当前情况下是否有任何转机来编写测试?
解决方案
我将findById(id)
方法更改getOne(id)
为如下 -
Mockito.when(lobbyRepository.getOne(anyLong())).thenReturn(lobbyTest);
并将我的测试用例更改为 -
Mockito.when(lobbyRepository.getOne(anyLong())).thenReturn(lobbyTest);
它现在工作正常。
推荐阅读
- sql - 内部连接语法错误,但现在确定错误是什么
- mysql - 如何从 MySQL 中的两个不同表中减去列中的值?
- python - 如何解决混淆 TypeError 和 Pickle
- makefile - 如何在 Makefile 中取消定义变量
- python - 如何在函数式编程中定义一个函数?
- azure - 将 Windows Azure 应用服务恢复到原始/默认状态
- machine-learning - 调整 SVR 的超参数
- airflow - 在气流中的 DAG 之间共享信息
- javascript - 如何在 Javascript 中创建密码验证功能?
- python - Python:获取href旁边的元素