When writing Junit test case using mockito for findById() JPA method I am getting error as java.util.NoSuchElementException: No value present

huangapple go评论81阅读模式
英文:

When writing Junit test case using mockito for findById() JPA method I am getting error as java.util.NoSuchElementException: No value present

问题

自 findById 方法的 JPA 返回类型是 Optional我正在使用 get 方法来获取确切的值但我无法实现单元测试

我的 Service 代码

public class LobbyService {
    // ...(你的其他代码部分)
    
    public Lobby getLobby(Long id) {
        Optional<Lobby> optionalLobby = this.lobbyRepository.findById(id);
        
        if (optionalLobby.isPresent()) {
            return optionalLobby.get();
        } else {
            throw new LobbyException(String.format("The lobby %d doesn't exist. Please check the lobby you are joining", id));
        }
    }
    
    // ...(你的其他代码部分)
}

// ...(你的其他代码部分)

请注意,我只是翻译了部分代码以解决你的问题。如果你需要更多帮助,可以继续询问。

英文:

Since findById method of JPA has return type as optional and I am using get method to get the exact value, I am unable to implement unit test.

My Service code:

public class LobbyService {

private final Logger log = LoggerFactory.getLogger(LobbyService.class);

private final LobbyRepository lobbyRepository;
private final UserRepository userRepository;

@Autowired
public LobbyService(@Qualifier(&quot;lobbyRepository&quot;) LobbyRepository lobbyRepository, @Qualifier(&quot;userRepository&quot;) 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&lt;LobbyGetDTO&gt; getAllLobbies(){
    List&lt;Lobby&gt; lobbyList = this.lobbyRepository.findAll();
    List&lt;LobbyGetDTO&gt; lobbyGetDTOList = new ArrayList&lt;&gt;();
    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 = &quot;This player id is invalid. Please provide proper id&quot;;
    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(&quot;Game is in progress. You can&#39;t join lobby in the middle of the game. Please try later&quot;);
    }

    //Checking if the user exists before adding the user to lobby
    userRepository.findById(userId)
            .orElseThrow(
                    () -&gt; new LobbyException(String.format(&quot;User with id: %d doesn&#39;t exist&quot;, userId))
            );
    String baseErrorMessage = &quot;The lobby cannot have more than 7 player. Please join different lobby&quot;;

    //Size of lobby is limited to maximum of 7 players.
    if(lobby.getPlayerIds().size()&gt;=7){
        throw new LobbyException(baseErrorMessage);
    }

    //Player should be unique in the lobby
    if(lobby.getPlayerIds().contains(userId)){
        baseErrorMessage = &quot;Player already exists in the lobby&quot;;
        throw new LobbyException(baseErrorMessage);
    }
    lobby.getPlayerIds().add(userId);
    saveOrUpdate(lobby);
}

public Lobby getLobby(Long id){

    Lobby lobby = this.lobbyRepository.findById(id).get();

    String baseErrorMessage = &quot;The lobby %d doesn&#39;t exist. Please check the lobby which you are joining&quot;;
    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 = &quot;The provided %s is not unique. Therefore, the lobby could not be created!&quot;;
    if (null != newLobby) {
        throw new LobbyException(String.format(baseErrorMessage, &quot;lobby name&quot;));
    }
}

}

My Junit code:

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(&quot;testLobby&quot;);
    lobbyTest.setHostPlayerId(1L);

    testUser = new User();
    testUser.setId(1L);
    testUser.setName(&quot;testName&quot;);
    testUser.setUsername(&quot;testUsername&quot;);

    // when -&gt; any object is being save in the userRepository -&gt; 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, ()-&gt;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,()-&gt;lobbyService.addPlayerToLobby(1L,1L));


}

@Test
public void addUserToLobby(){

    List&lt;Long&gt; playerList  = new ArrayList&lt;&gt;();
    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&lt;Long&gt; playerList  = new ArrayList&lt;&gt;();
    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,()-&gt;lobbyService.addPlayerToLobby(1L,1L));


}

@Test
public void addMoreThanSevenPlayerToLobby(){

    List&lt;Long&gt; playerList  = new ArrayList&lt;&gt;();
    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,()-&gt;lobbyService.addPlayerToLobby(1L,8L));

}

}

Error Message:

No value present
java.util.NoSuchElementException: No value present
	at java.base/java.util.Optional.get(Optional.java:148)

I don't want to change my return type to Optional for findById. If there is any turnaround to write test in the current scenario?

答案1

得分: 0

尝试用以下代码替换你的测试代码:

Mockito.when(lobbyRepository.findById(anyLong())).thenReturn(Optional.ofNullable(lobbyTest));
英文:

Try to replace your test code with:

Mockito.when(lobbyRepository.findById(anyLong())).thenReturn(Optional.ofNullable(lobbyTest));

答案2

得分: 0

你必须模拟 lobbyRepository.findById() 和 id 来进行测试。在你的测试用例中,进行以下操作:

Lobby mockedLobby = getConcreteLobby();
Optional<Lobby> optionalLobby = Optional.of(mockedLobby);
when(lobbyRepository.findbyId(anyLong())).thenReturn(optionalLobby);

还有其他方法,但这可能适用于你的情况。

还有一件事:你不应该像你之前做的那样测试一个 Optional。你必须确保代码返回一个 Optional - 无论是空还是非空 - 并通过测试 Optional.isPresent() 来处理它。在你的情况下,如果你真的想测试是否为 null,使用 getOrElse(null) 而不是 get()。

英文:

You must mock both lobbyRepository.findById() and id to test. In your test case, do:

Lobby mockedLobby = getConcreteLobby();
Optional&lt;Lobby&gt; optionalLobby = Optional.of(mockedLobby);
when(lobbyRepository.findbyId(anyLong())).thenReturn(optionalLobby);

There are other approaches, but this probably will make it for your scenario.

One more thing: you should not test an Optional as you did. You must assure the code returns an Optional - empty or not -, and deal with it testing for Optional.isPresent(). In your case, if you really want to test for null, use getOrElse(null) instead of get().

答案3

得分: 0

我将 findById(id) 方法更改为如下的 getOne(id) 方法 -

Mockito.when(lobbyRepository.getOne(anyLong())).thenReturn(lobbyTest);

并且将我的测试用例更改为 -

Mockito.when(lobbyRepository.getOne(anyLong())).thenReturn(lobbyTest);

现在正常运行。

英文:

I changed the findById(id) method to getOne(id) as below -

Mockito.when(lobbyRepository.getOne(anyLong())).thenReturn(lobbyTest);

And changed my test case to -

Mockito.when(lobbyRepository.getOne(anyLong())).thenReturn(lobbyTest);

Its working fine now.

答案4

得分: 0

Use doReturn(Optional.of(yourMockObj)).when(employeeRepository).findById(idToFind);

Sample Code

@Test
@Order(2)
@DisplayName("Test getEmployeeByEmployeeId")
public void test_getEmployeeByEmployeeId() throws EmployeeNotFoundException
{
    // Setup the mock repo
    Long employeeId = 1L;
    Employee e1ForMock = new Employee(employeeId, "Aravinth P", 29, "aravinth.p@email.com");
    doReturn(Optional.of(e1ForMock)).when(employeeRepository).findById(employeeId);
    // Make the service call
    Employee e1ByService = employeeServiceImpl.getEmployeeByEmployeeId(employeeId);
    // Assert the response
    assertNotNull(e1ByService, "Employee with employeeId : " + employeeId + " not found");
    assertEquals(employeeId, e1ByService.getEmployeeId());
    assertEquals(e1ForMock.getName(), e1ByService.getName());
    assertEquals(e1ForMock.getAge(), e1ByService.getAge());
    assertEquals(e1ForMock.getEmail(), e1ByService.getEmail());
}
英文:

Use doReturn(Optional.of(yourMockObj)).when(employeeRepository).findById(idToFind);

Sample Code

@Test
@Order(2)
@DisplayName(&quot;Test getEmployeeByEmployeeId&quot;)
public void test_getEmployeeByEmployeeId() throws EmployeeNotFoundException
{
	// Setup the mock repo
	Long employeeId = 1L;
	Employee e1ForMock = new Employee(employeeId, &quot;Aravinth P&quot;, 29, &quot;aravinth.p@email.com&quot;);
	doReturn(Optional.of(e1ForMock)).when(employeeRepository).findById(employeeId);
	// Make the service call
	Employee e1ByService = employeeServiceImpl.getEmployeeByEmployeeId(employeeId);
	// Assert the response
	assertNotNull(e1ByService,&quot;Employee with employeeId : &quot;+employeeId+&quot; not found&quot;);
	assertEquals(employeeId,e1ByService.getEmployeeId());
	assertEquals(e1ForMock.getName(), e1ByService.getName());
	assertEquals(e1ForMock.getAge(), e1ByService.getAge());
	assertEquals(e1ForMock.getEmail(), e1ByService.getEmail());
}

huangapple
  • 本文由 发表于 2020年4月10日 19:47:27
  • 转载请务必保留本文链接:https://go.coder-hub.com/61139620.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定