有人坚持认为集成测试是种种种错误和错误的方法 -一切都必须经过单元测试,这意味着您必须模拟依赖项;由于种种原因,我并不总是喜欢这种选择。
我发现在某些情况下,单元测试根本无法证明任何事情。
让我们以以下(简单,幼稚的)存储库实现(在PHP中)为例:
class ProductRepository
{
private $db;
public function __construct(ConnectionInterface $db) {
$this->db = $db;
}
public function findByKeyword($keyword) {
// this might have a query builder, keyword processing, etc. - this is
// a totally naive example just to illustrate the DB dependency, mkay?
return $this->db->fetch("SELECT * FROM products p"
. " WHERE p.name LIKE :keyword", ['keyword' => $keyword]);
}
}
假设我想在测试中证明该存储库实际上可以找到与各种给定关键字匹配的产品。
缺少与真实连接对象的集成测试,我如何才能知道这实际上是在生成真实查询-并且那些查询实际上按照我认为的方式工作?
如果必须在单元测试中模拟连接对象,则只能证明“它会生成预期的查询”之类的东西-但这并不意味着它实际上就可以工作 ……也就是说,也许它正在生成查询我预料到了,但也许该查询没有执行我认为的操作。
换句话说,我感觉像是一个对生成的查询进行断言的测试,基本上没有价值,因为它正在测试findByKeyword()
方法的实现方式,但这并不能证明它实际上是有效的。
这个问题不仅限于存储库或数据库集成-似乎在许多情况下都适用,在这种情况下,对使用模拟(test-double)的使用进行断言只能证明事情的实现方式,而不是它们是否将要实现。实际工作。
您如何处理此类情况?
在这种情况下,集成测试真的“不好”吗?
我的观点是,最好测试一件事,并且我也理解为什么集成测试会导致无数的代码路径,而所有这些代码路径都无法测试-但就服务(例如存储库)而言,其唯一目的是要与另一个组件交互,如何在没有集成测试的情况下真正测试任何东西?