La plupart du temps, les tests de base de données en mémoire sont plus simples que les simulations. C'est aussi beaucoup plus flexible. Et il vérifie également que les fichiers de migration sont bien exécutés (lorsqu'il y a des fichiers de migration).
Voir ce pseudo code:
class InMemoryTest
{
/** @test */
public function user_repository_can_create_a_user()
{
$this->flushDatabase();
$userRepository = new UserRepository(new Database());
$userRepository->create('name', 'email@email.com');
$this->seeInDatabase('users', ['name' => 'name', 'email' => 'email@email.com']);
}
}
class MockingDBTest
{
/** @test */
public function user_repository_can_create_a_user()
{
$databaseMock = MockLib::mock(Database::class);
$databaseMock->shouldReceive('save')
->once()
->withArgs(['users', ['name' => 'name', 'email' => 'email@email.com']]);
$userRepository = new UserRepository($databaseMock);
$userRepository->create('name', 'email@email.com');
}
}
Le InMemoryTestne dépend pas de la façon dont Databaseest mis en œuvre UserRepositorypour fonctionner. Il utilise simplement l' UserRepositoryinterface publique ( create) puis l'affirme. Ce test ne se cassera pas si vous modifiez l'implémentation mais il est plus lent.
Pendant ce temps, le MockingDBTestrepose entièrement sur la façon dont il Databaseest mis en œuvre UserRepository. En fait, si vous modifiez l'implémentation tout en la faisant fonctionner d'une autre manière, ce test échouerait.
Le meilleur des deux mondes serait d'utiliser un faux implémentant l' Databaseinterface:
class UsingAFakeDatabaseTest
{
/** @test */
public function user_repository_can_create_a_user()
{
$fakeDatabase = new FakeDatabase();
$userRepository = new UserRepository($fakeDatabase);
$userRepository->create('name', 'email@email.com');
$this->assertEquals('name', $fakeDatabase->datas['users']['name']);
$this->assertEquals('email@email.com', $fakeDatabase->datas['users']['email']);
}
}
interface DatabaseInterface
{
public function save(string $table, array $datas);
}
class FakeDatabase implements DatabaseInterface
{
public $datas;
public function save(string $table, array $datas)
{
$this->datas[$table][] = $datas;
}
}
C'est beaucoup plus expressif, plus facile à lire et à comprendre, et cela ne dépend pas de l'implémentation de la base de données réelle effectuée dans les couches supérieures du code.