На чем следует сфокусировать тестирование при разработке приложения по методологии DDD (Domain-Driven Design)?

Ответ

При разработке по DDD тестирование должно быть сфокусировано на доменном слое (Domain Layer), так как именно он содержит ключевую бизнес-логику, правила и инварианты, которые являются ядром и главной ценностью приложения.

Приоритеты тестирования (от высшего к низшему):

  1. Агрегаты (Aggregates): Это главный объект тестирования. Тесты должны проверять:

    • Соблюдение инвариантов: Агрегат не должен переходить в некорректное состояние. Например, сумма заказа не может быть отрицательной.
    • Корректность выполнения команд: Все методы, изменяющие состояние агрегата, должны работать правильно.
    • Генерацию доменных событий: После выполнения действия агрегат должен порождать правильные события (например, OrderPlaced, ItemAdded).
  2. Объекты-значения (Value Objects): Тесты проверяют их валидацию при создании и неизменяемость (immutability).

  3. Доменные сервисы (Domain Services): Тестируется логика, которая координирует действия между несколькими агрегатами и не принадлежит ни одному из них.

Пример теста для агрегата Order:

func TestOrder_AddItem_EnforcesInvariants(t *testing.T) {
    // Arrange: создаем заказ
    order := NewOrder("order-123")

    // Act: добавляем товар
    err := order.AddItem("product-abc", 2, 150.0)

    // Assert: проверяем результат
    if err != nil {
        t.Fatalf("Неожиданная ошибка при добавлении товара: %v", err)
    }

    // Проверяем, что инвариант (общая стоимость) соблюдается
    if order.Total() != 300.0 {
        t.Errorf("Ожидаемая стоимость 300.0, получено %f", order.Total())
    }

    // Проверяем, что было сгенерировано доменное событие
    events := order.Events()
    if len(events) != 1 || events[0].Name != "ItemAddedToOrder" {
        t.Error("Ожидалось событие ItemAddedToOrder")
    }
}

Тесты для других слоев (Application, Infrastructure) также важны, но они вторичны. Инфраструктурный слой (например, репозитории) часто покрывается интеграционными тестами, а не юнит-тестами.