当我们向数据访问代码编写测试时,是否应该测试其公共API的每种方法?
一开始听起来很自然。 毕竟,如果我们不对所有内容进行测试,那么如何知道我们的代码可以按预期工作呢?
这个问题为我们提供了重要的线索:
我们的代码 。
我们应该只对自己的代码编写测试。
什么是我们自己的代码?
有时很难确定我们应该测试的代码。 原因是我们的数据访问代码与将信息保存到使用的数据存储中或从中读取信息时所使用的库或框架紧密集成在一起。
例如,如果我们要创建一个向Todo对象提供CRUD操作的Spring Data JPA存储库,则应创建一个扩展CrudRepository接口的接口。 TodoRepository接口的源代码如下所示:
import org.springframework.data.repository.CrudRepository;public TodoRepository extends CrudRepository<Todo, Long> {}
即使我们没有向存储库接口添加任何方法, CrudRepository接口也声明了许多可供使用我们存储库接口的类使用的方法。
这些方法不是我们的代码,因为它们是由Spring Data团队实现和维护的。 我们只使用它们。
另一方面,如果我们向存储库添加自定义查询方法,情况将发生变化。 假设我们必须找到标题等于给定搜索词的所有待办事项。 在将此查询方法添加到存储库接口后,其源代码如下所示:
import org.springframework.data.repository.CrudRepository;
import org.springframework.data.repository.query.Param;public TodoRepository extends CrudRepository<Todo, Long> {@Query("SELECT t FROM Todo t where t.title=:searchTerm")public List<Todo> search(@Param("searchTerm") String searchTerm)
}
可以很容易地断言该方法是我们自己的代码,这就是为什么我们应该对其进行测试。 但是,事实有点复杂。 即使JPQL查询是由我们编写的,Spring Data JPA仍会提供将查询转发给使用过的JPA提供程序的代码。
而且,我仍然认为该查询方法是我们自己的代码,因为其中最重要的部分是由我们编写的。
如果要标识自己的数据访问代码,则必须找到每种方法的基本部分。 如果这部分是我们编写的,则应将该方法视为自己的代码。
这一切都是显而易见的,更有趣的问题是:
我们应该测试吗?
我们的存储库接口为使用它的类提供了两种方法:
- 它提供了由CrudRepository接口声明的方法。
- 它提供了我们编写的查询方法。
我们是否应该将集成测试写到TodoRepository接口并测试所有这些方法?
不,我们不应该这样做,因为
- CrudRepository接口声明的方法不是我们自己的代码。 这段代码是由Spring Data团队编写和维护的,他们已经确保它可以工作。 如果我们不相信他们的代码有效,则不应使用它。
- 我们的应用程序可能有许多存储库接口,这些接口扩展了CrudRepository接口。 如果决定对CrudRepository接口声明的方法编写测试,则必须对所有存储库编写这些测试。 如果选择这种方式,我们将花费大量时间为其他人的代码编写测试,坦率地说,这样做是不值得的。
- 我们自己的代码可能是如此简单,以至于将测试写入我们的存储库是没有意义的。
换句话说,我们应该集中精力寻找这个问题的答案:
我们应该将集成测试写入我们的存储库方法(由我们编写的方法),还是只编写端到端测试?
这个问题的答案取决于我们存储库方法的复杂性。 我知道复杂性是一个模糊的词,这就是为什么我们需要某种准则来帮助我们找到测试存储库方法的最佳方法的原因。
做出此决定的一种方法是考虑测试每种可能情况所需的工作量。 这是有道理的,因为:
- 将集成测试写入单个存储库方法比将相同的测试写入使用存储库方法的功能所需的工作更少。
- 无论如何,我们都必须端对端地编写。
这就是为什么最小化我们的投资(时间)和最大化我们的利润(测试覆盖率)的原因。 我们可以按照以下规则进行操作:
- 如果我们只编写几个测试就可以测试所有可能的场景,那么我们就不应该浪费时间将集成测试写入我们的存储库方法。 我们应该编写端到端测试,以确保该功能按预期工作。
- 如果我们需要编写多个测试,则应将集成测试写入存储库方法,而仅编写一些端到端测试(烟雾测试)。
摘要
这篇博客文章教会了我们两件事:
- 我们不应该浪费时间将测试编写到其他人编写的数据访问框架(或库)中。 如果我们不信任该框架(或库),则不应使用它。
- 有时我们也不应该对数据访问代码编写集成测试。 如果经过测试的代码足够简单(我们可以通过编写一些测试来涵盖所有情况),则应该通过编写端到端测试来对其进行测试。
翻译自: https://www.javacodegeeks.com/2014/07/writing-tests-for-data-access-code-dont-test-the-framework.html