Design injected dependencies so collaborators can be swapped for test doubles in unit tests.
Testing with Dependency Injection
// Hard-coded dependency — HARD TO TEST
class ReportGenerator {
public function generate(): array {
$pdo = new PDO("mysql:host=prod-db;dbname=app", "user", "pass"); // hardcoded!
return $pdo->query("SELECT * FROM sales")->fetchAll();
}
}
// Injected dependency — EASY TO TEST
class ReportGenerator {
public function __construct(private PDO $pdo) {}
public function generate(): array {
return $this->pdo->query("SELECT * FROM sales")->fetchAll();
}
}
// Test with in-memory SQLite
class ReportGeneratorTest extends TestCase {
public function testGenerate(): void {
$pdo = new PDO("sqlite::memory:");
$pdo->exec("CREATE TABLE sales (id INT, amount FLOAT)");
$pdo->exec("INSERT INTO sales VALUES (1, 99.99)");
$report = (new ReportGenerator($pdo))->generate();
$this->assertCount(1, $report);
$this->assertEquals(99.99, $report[0]["amount"]);
}
}