【问题标题】:How can i treat UserNotFound exception on endpoints unit tests?如何处理端点单元测试中的 UserNotFound 异常?
【发布时间】:2020-06-17 00:02:59
【问题描述】:

我正在开发一个带有 User 实体的 Spring Boot CRUD RESTful API,该实体由两个参数组成:nameid。我的测试框架是 JUnit

我面临的问题是我不知道如何在我的服务单元测试中处理可抛出的 UserNotFound 异常。

我的“按 id 列出用户”“按 id 删除用户”中可能有 “{id} 找不到用户” 异常 em> 和 "Update user by id" 如您所见(我将仅列出两个端点以使其更短):

@Service
public class DeleteUserService {

    @Autowired
    UserRepository repository;

    public void deleteUser(Long id) {
        Optional<User> userOptional = repository.findById(id);
        if (!userOptional.isPresent()) {
            throw new UserNotFoundException(id);
        } else {
            repository.deleteById(id);
        }
    }
}

@Service
public class DetailUserService {

    @Autowired
    UserRepository repository;

    public Optional<User> listUser(Long id) {

        Optional<User> user = repository.findById(id);
        if (!user.isPresent()) {
            throw new UserNotFoundException(id);
        } else {
            return repository.findById(id);
        }
    }
}

到目前为止没有任何问题,我的端点工作正常。 UserNotFound 代码是:

@ControllerAdvice
public class UserNotFoundAdvice {

    @ResponseBody
    @ExceptionHandler(UserNotFoundException.class)
    @ResponseStatus(HttpStatus.NOT_FOUND)
    String userNotFoundHandler(UserNotFoundException ex) {
        return ex.getMessage();
    }
}

public class UserNotFoundException extends RuntimeException {
    public UserNotFoundException(Long id) {
        super("Could not find user with id " + id + ".");
    }
}

单元测试(这是编写的主要原因):

@RunWith(MockitoJUnitRunner.class)
public class DeleteUserServiceTest {

    @Mock
    private UserRepository userRepository;

    @InjectMocks
    private DeleteUserService deleteUserService;

    @Test
    public void whenGivenId_shouldDeleteUser_ifFound(){
        User user = new User();
        user.setId(89L);

        deleteUserService.deleteUser(user.getId());
        verify(userRepository).deleteById(user.getId());
    }
}

@RunWith(MockitoJUnitRunner.class)
public class DetailUserServiceTest {

    @Mock
    private UserRepository userRepository;

    @InjectMocks
    private DetailUserService detailUserService;

    @Test
    public void whenGivenId_shouldReturnUser_ifFound() {
        User user = new User();
        user.setId(89L);

        Optional<User> userMock = Optional.of(user);

        when(userRepository.findById(user.getId())).thenReturn(userMock);

        Optional<User> expected = detailUserService.listUser(user.getId());

        assertThat(expected).isSameAs(userMock);
        verify(userRepository).findById(user.getId());
    }
}

如您所见,这些单元测试代码中缺少一些东西,即 UserNotFound 的行为。也许它没有正确模拟或单元测试代码中缺少其他东西?

如果有人能帮我解决这个问题,我将不胜感激!对不起,如果帖子太长,我已经尽力解释了!

【问题讨论】:

    标签: java api rest unit-testing junit


    【解决方案1】:

    如果我理解正确,您需要在找不到用户并且抛出异常时测试行为。

    这里是关于如何测试异常的链接:https://www.baeldung.com/junit-assert-exception

    此外,您还可以验证是否未调用按 id 删除或按 id 查找:

    verify(userRepository, never()).findById(user.getId()); 
    or
    verify(userRepository, Mockito.times(0)).findById(user.getId());
    

    和 deleteById 一样

    要测试异常处理程序是否被调用并正常工作,您需要进行集成测试。

    【讨论】:

    • 感谢您的回答,但我仍然找不到使这项工作的方法。我在单元测试中收到 org.mockito.exceptions.verification.TooManyActualInvocations 错误消息。
    • 我很确定这与此有关:可选 user = repository.findById(id); if (!user.isPresent()) { throw new UserNotFoundException(id); }
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-11-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-06-02
    相关资源
    最近更新 更多