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 InMemoryTest
ne dépend pas de la façon dont Database
est mis en œuvre UserRepository
pour fonctionner. Il utilise simplement l' UserRepository
interface 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 MockingDBTest
repose entièrement sur la façon dont il Database
est 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' Database
interface:
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.