In den meisten Fällen ist das Testen von In-Memory-Datenbanken einfacher als das Verspotten. Es ist auch viel flexibler. Außerdem werden die Migrationsdateien getestet (wenn Migrationsdateien vorhanden sind).
Siehe diesen Pseudocode:
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');
}
}
Das InMemoryTest
hängt nicht davon ab, wie Database
es in UserRepository
die Arbeit implementiert wird . Es verwendet einfach die UserRepository
öffentliche Schnittstelle ( create
) und behauptet dann dagegen. Dieser Test wird nicht unterbrochen, wenn Sie die Implementierung ändern, aber er ist langsamer.
In der Zwischenzeit hängt das MockingDBTest
voll davon ab, wie Database
es umgesetzt wird UserRepository
. Wenn Sie die Implementierung ändern, sie aber dennoch auf andere Weise funktionieren lassen, wird dieser Test unterbrochen.
Das Beste aus beiden Welten wäre die Verwendung einer Fälschung, die die Database
Schnittstelle implementiert :
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;
}
}
Das ist viel ausdrucksvoller, leichter zu lesen und zu verstehen und hängt nicht von der Implementierung der tatsächlichen Datenbank in höheren Codeebenen ab.