Ответ
При разработке по DDD тестирование должно быть сфокусировано на доменном слое (Domain Layer), так как именно он содержит ключевую бизнес-логику, правила и инварианты, которые являются ядром и главной ценностью приложения.
Приоритеты тестирования (от высшего к низшему):
-
Агрегаты (Aggregates): Это главный объект тестирования. Тесты должны проверять:
- Соблюдение инвариантов: Агрегат не должен переходить в некорректное состояние. Например, сумма заказа не может быть отрицательной.
- Корректность выполнения команд: Все методы, изменяющие состояние агрегата, должны работать правильно.
- Генерацию доменных событий: После выполнения действия агрегат должен порождать правильные события (например,
OrderPlaced
,ItemAdded
).
-
Объекты-значения (Value Objects): Тесты проверяют их валидацию при создании и неизменяемость (immutability).
-
Доменные сервисы (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) также важны, но они вторичны. Инфраструктурный слой (например, репозитории) часто покрывается интеграционными тестами, а не юнит-тестами.