La mayoría de las veces, las pruebas de bases de datos en memoria son más simples que las burlas. También es mucho más flexible. Y también prueba que los archivos de migración estén bien (cuando hay archivos de migración).
Vea este pseudocódigo:
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');
}
}
El InMemoryTest
no depende de cómo Database
se implementa en el UserRepository
trabajo. Simplemente usa la UserRepository
interfaz pública ( create
) y luego afirma contra ella. Esa prueba no se romperá si cambia la implementación, pero es más lenta.
Mientras tanto, MockingDBTest
depende totalmente de cómo Database
se implementa UserRepository
. De hecho, si cambia la implementación pero aún así hace que funcione de otra manera, esa prueba se rompería.
Lo mejor de ambos mundos sería usar una falsa implementación de la Database
interfaz:
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;
}
}
Eso es mucho más expresivo, más fácil de leer y entender, y no depende de la implementación de la base de datos real realizada en las capas superiores del código.