ほとんどの場合、インメモリデータベーステストはモックよりも単純です。また、はるかに柔軟です。また、移行ファイルが適切に実行されていることもテストします(移行ファイルがある場合)。
この疑似コードを参照してください:
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');
}
}
は、InMemoryTest
動作するようDatabase
に実装される方法に依存しませんUserRepository
。単にUserRepository
パブリックインターフェイス(create
)を使用し、それに対してアサートします。実装を変更してもテストは中断しませんが、速度は遅くなります。
一方、は、への実装MockingDBTest
方法に完全に依存Database
していUserRepository
ます。実際、実装を変更しても別の方法で機能させると、そのテストは失敗します。
両方の長所は、インターフェイスを実装する偽物を使用することDatabase
です。
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;
}
}
それはより表現力があり、読みやすく、理解しやすく、コードの上位層で行われる実際のデータベースの実装に依存しません。