Na maioria das vezes, o teste de banco de dados na memória é mais simples do que zombar. Também é muito mais flexível. E também testa se os arquivos de migração são bem executados (quando há arquivos de migração).
Veja este pseudo-có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');
}
}
O InMemoryTest
não depende de como Database
é implementado no UserRepository
trabalho. Ele simplesmente usa a UserRepository
interface pública ( create
) e, em seguida, afirma contra ela. Esse teste não será interrompido se você alterar a implementação, mas for mais lento.
Enquanto isso, ele MockingDBTest
depende totalmente de como Database
é implementado UserRepository
. De fato, se você alterar a implementação, mas ainda fazê-la funcionar de outra maneira, esse teste será interrompido.
O melhor dos dois mundos seria usar uma falsa implementação da 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;
}
}
Isso é muito mais expressivo, mais fácil de ler e entender, e não depende da implementação do banco de dados real, feito nas camadas superiores do código.