Il più delle volte, il test del database in memoria è più semplice del deridere. È anche molto più flessibile. Inoltre, verifica che i file di migrazione siano eseguiti correttamente (quando sono presenti file di migrazione).
Vedi questo pseudo codice:
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');
}
}
Il InMemoryTestnon dipende da come Databaseviene implementato in UserRepositoryal lavoro. Usa semplicemente l' UserRepositoryinterfaccia pubblica ( create) e quindi afferma contro di essa. Quel test non si interromperà se cambi l'implementazione ma è più lento.
Nel frattempo, MockingDBTesttutto dipende da come Databaseviene implementato UserRepository. In effetti, se si modifica l'implementazione ma si fa ancora funzionare in un altro modo, tale test si interromperà.
Il meglio di entrambi i mondi sarebbe usare un falso implementando l' Databaseinterfaccia:
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;
}
}
Questo è molto più espressivo, più facile da leggere e da capire e non dipende dall'implementazione del database effettivo fatto nei livelli più alti del codice.