В чем разница между mock и fixture в pytest?

Ответ

Хотя оба инструмента используются для подготовки тестового окружения, у них принципиально разные цели:

  • Mock (Мок) — это объект-заглушка, который заменяет (подменяет) реальную зависимость (например, модуль, класс, функцию) для изоляции тестируемого кода. Это позволяет тестировать компонент, не затрагивая его внешние зависимости (API, базу данных, файловую систему).

  • Fixture (Фикстура) — это функция, которая предоставляет данные, объекты или настраивает состояние для тестов. Она используется для подготовки окружения и устранения дублирования кода (принцип DRY — Don't Repeat Yourself).

Сравнение:

Аспект Mock Fixture
Основная цель Изоляция кода, имитация поведения Подготовка данных и состояния, переиспользование кода
Что делает? Подменяет реальный объект Предоставляет готовый объект или данные
Источник unittest.mock или pytest-mock (обертка mocker) Декоратор @pytest.fixture
Пример Заменить обращение к внешнему API на возврат заранее заданного JSON Создать подключение к тестовой БД или вернуть объект пользователя

Пример совместного использования

Представим, что у нас есть функция, которая получает данные пользователя из БД и возвращает его возраст.

import pytest

# ФИКСТУРА: предоставляет тестовые данные
@pytest.fixture
def sample_user_data():
    """Эта фикстура просто возвращает словарь с данными."""
    return {"id": 1, "name": "Alice", "age": 30}

# Функция, которую мы хотим протестировать
# (предполагается, что db.get_user обращается к реальной БД)
from my_app import logic, db

def test_get_user_age(mocker, sample_user_data):
    # МОК: подменяем функцию обращения к БД
    # Теперь при вызове db.get_user(1) не будет реального запроса к БД,
    # а вернется значение из фикстуры sample_user_data.
    mocker.patch('my_app.db.get_user', return_value=sample_user_data)

    # Вызываем тестируемую логику
    age = logic.get_user_age(1)

    # Проверяем, что наша логика правильно извлекла возраст
    assert age == 30

В этом примере:

  1. Фикстура sample_user_data подготовила нам тестовые данные.
  2. Мок mocker.patch изолировал тест от реальной базы данных, заставив функцию db.get_user вернуть наши данные.