Some people maintain that integration tests are all kinds of bad and wrong - everything must be unit-tested, which means you have to mock dependencies; an option which, for various reasons, I'm not always fond of.
I find that, in some cases, a unit-test simply doesn't prove anything.
Let's take the following (trivial, naive) repository implementation (in PHP) as an example:
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]);
}
}
Let's say I want to prove in a test that this repository can actually find products matching various given keywords.
Short of integration testing with a real connection object, how can I know that this is actually generating real queries - and that those queries actually do what I think they do?
If I have to mock the connection object in a unit-test, I can only prove things like "it generates the expected query" - but that doesn't mean it's actually going to work... that is, maybe it's generating the query I expected, but maybe that query doesn't do what I think it does.
In other words, I feel like a test that makes assertions about the generated query, is essentially without value, because it's testing how the findByKeyword()
method was implemented, but that doesn't prove that it actually works.
This problem isn't limited to repositories or database integration - it seems to apply in a lot of cases, where making assertions about the use of a mock (test-double) only proves how things are implemented, not whether they're going to actually work.
How do you deal with situations like these?
Are integration tests really "bad" in a case like this?
I get the point that it's better to test one thing, and I also understand why integration testing leads to myriad code-paths, all of which cannot be tested - but in the case of a service (such as a repository) whose only purpose is to interact with another component, how can you really test anything without integration testing?