ส่วนใหญ่แล้วการทดสอบฐานข้อมูลในหน่วยความจำนั้นง่ายกว่าการล้อเลียน นอกจากนี้ยังยืดหยุ่นได้มากกว่า และมันยังทดสอบว่าไฟล์การโยกย้ายนั้นทำได้ดี (เมื่อมีไฟล์การโยกย้าย)
ดูรหัสเทียมนี้:
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;
}
}
นั่นเป็นวิธีที่ชัดเจนอ่านและเข้าใจได้ง่ายขึ้นและไม่ได้ขึ้นอยู่กับการใช้ฐานข้อมูลจริงที่ทำในเลเยอร์ของโค้ดที่สูงขึ้น