Тестування - БД в пам'яті проти глузування


12

Коли пишуть тести, чому б хтось хотів використовувати базу даних в пам'яті, щоб просто глузувати з даних?

Я міг бачити, що бази даних в пам'яті можуть бути корисними для тестування сховищ. Але якщо використовувати фреймворк (наприклад, Spring Data), тестування сховищ було б тестуванням фреймворку, а не дійсно логікою програми.

Однак глузування здається більш швидким і дотримується тієї ж схеми, яка зазвичай використовується при написанні одиниць тестів та TDD.

То що мені не вистачає? Коли / навіщо корисна база даних пам'яті?

Відповіді:


14

Знущання - це ідеальне рішення для одиничних тестів, і його також можна використовувати для інтеграційних тестів для підвищення швидкості, але це не забезпечує той самий рівень впевненості, як при використанні бази даних в пам'яті. Вам слід записати тести, де ви налаштовуєте всю програму якомога ближче до того, як вона налаштована на виробництво, і запускаєте проти неї автоматичні тести. Ці тести повинні використовувати реальну базу даних - або в пам'яті, докер, VM або інше розгортання.

Але якщо використовувати фреймворк (наприклад, Spring Data), тестування сховищ було б тестуванням фреймворку, а не дійсно логікою програми.

Використовуючи реальну базу даних, ви перевіряєте, що ви фактично конфігуруєте та використовуєте рамку правильно. Далі можуть бути недоліки в рамках, які виявляються лише при тестуванні з фактичною базою даних (надуманий приклад: Spring Data не підтримує версію 9.2 PostgreSQL).

Я б написав більшу частину мого тестового покриття проти знущаються джерел, але я б написав декілька тестів для кінцевих випадків використання, використовуючи реальну базу даних.


Якщо це тест Unit, ви протестуєте фреймворк окремо від шару, який використовує фреймворк. Завжди повинні бути деякі інтеграційні тести після того, як все тестування блоку буде зроблено.
Деніз

2

Здебільшого тестування баз даних у пам'яті простіше, ніж глузування. Це також набагато гнучкіше. А також тестує, що файли міграції зроблені добре (коли є файли міграції).

Дивіться цей псевдо-код:

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;
    }
}

Таким чином виразніше, простіше читати та розуміти, і це не залежить від реалізації фактичної бази даних, зробленої у вищих шарах коду.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.