An integration test needs a real database or it proves nothing

A repository test against a mocked connection asserts that the code calls the methods you expected, which is a restatement of the code rather than a check on it.

// asserts nothing about whether the query is correct
$pdo = $this->createMock(PDO::class);
$pdo->method('prepare')->willReturn($stmt);

// asserts that MySQL agrees
public function testFindsByEmailCaseInsensitively(): void
{
    $this->repo->save(new Customer('[email protected]'));

    $this->assertNotNull($this->repo->byEmail('[email protected]'));
}

That test only passes because of the column collation, which no mock will ever tell you. The same applies to unique constraints, timezone handling, decimal rounding and the maximum length of an index — every one of them is a property of the database rather than of the code. Running the suite against both MySQL and MariaDB found two behavioural differences on one project, and neither was in any code we had written.