关于java:服务层的异常测试

Exception test for service layer

本问题已经有最佳答案,请猛点这里访问。

我有一门课看起来像这样:

1
2
3
4
5
6
7
8
9
10
@Service
@Transactional
public class BookServiceImpl implements BookService {
    @Autowired
    private BookRepository bookRepository;

    public void removeOne(Long id) throws DataAccessException {
        bookRepository.delete(id);
    }
}

我的异常测试看起来像这样

1
2
3
4
5
6
7
8
9
10
@Rule
public final ExpectedException exception = ExpectedException.none();

@Test
public void removeOneThrowsNullPointerException() {
    BookService foo = new BookServiceImpl();

    exception.expect(NullPointerException.class);
    foo.removeOne(1L);
}

现在这个测试通过了,但是首先,为什么必须实例化BookService类,通常这个测试会通过,如果是一个简单的单元测试,因为我们有一本ID为1L的书,但是现在它是空的,我已经阅读了关于@rule的文章,实际发生了什么?这是在removeOne()方法中查找异常的适当测试吗?


可能你的服务中有NullPointerExceptionbookRepository上。换句话说,它没有正确地自动连线。您是否尝试调试此测试以查看对象究竟是什么空值?

编写正确测试有两种可能的方法:

  • 对于集成测试,您需要关注自动连接所有依赖项,请阅读有关Spring和测试的内容。
  • 对于纯单元测试,您需要关心模拟所有依赖项。
  • 使用@rule是测试异常情况的正确方法。

    更新:测试服务层异常情况的最简单方法是模拟存储库类以抛出DataAccessException并将其注入服务类:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    @Rule
    public final ExpectedException exception = ExpectedException.none();

    @Test
    public void removeOneThrowsDataAccessException() {
        BookRepository mockedRepository = Mock(BookRepository.class);
        when(mockedRepository.get(1L)).thenThrow(new DataAccessException());

        BookService foo = new BookServiceImpl(mockedRepository);

        exception.expect(DataAccessException.class);

        foo.removeOne(1L);
    }