Как создаются агрегаты для тестирования других агрегатов? - PullRequest
0 голосов
/ 15 ноября 2018

Предположим, у меня есть агрегат, который для некоторой операции требует существования другого агрегата.Давайте предположим, что у меня есть car и garage.Может существовать команда с именем ParkInGarage, которая выглядит следующим образом:

public class ParkInGarage {

    @TargetAggregateIdentifier
    public final UUID carId;

    public final Garage garage;

    //... constructor omitted
}

У меня чтение , что для проверки существования агрегата рекомендуется использовать загруженный файл.агрегировать в командах, поскольку это уже подразумевает его существование (в отличие от передачи garageId).

Теперь, когда юнит-тестирование Car с использованием приборов Аксона , я не могу просто создать экземплярмой Garage, сказав new Garage(buildGarageCmd).Будет сказано:

java.lang.IllegalStateException: Невозможно запросить текущий Scope, если ни один не активен

, так как инфраструктура не была настроена.Как бы я протестировал такой случай, или я должен по-другому проектировать агрегат?

Абстрактный, реальный пример

Корень агрегата, с которым я работаю, может иметь ссылку на себя, чтобы сформироватьдревовидная структура указанного совокупного корня.Давайте назовем это Node.

@Aggregate
public class Node {
    private Node parentNode;
}

После создания я могу передать Optional<Node> в качестве родителя или установить родителя позже, используя отдельную команду.Вопрос о том, должен ли родитель быть определен как экземпляр или по идентификатору, является частью вопроса.

public class AttachNodeCmd {
    @TargetAggregateIdentifier
    public final UUID nodeId;
    public final Optional<Node> parentNode;
}

В обработчике команд мне нужно проверить, будет ли присоединение узла к данному родителю вводить цикл (структурадолжно быть деревом, а не общим графом).

@CommandHandler
public Node(AttachNodeCmd command) {
    if (command.parentNode.isPresent()) {
        Node currentNode = command.parentNode.get();
        while (currentNode != null) {
            if (currentNode.equals(this)) throw new RecursionException();
            currentNode = currentNode.parentNode.orElse(null);
        }
    }

    //Accept the command by applying() an Event
}

В какой-то момент родительский экземпляр должен быть создан для выполнения этих проверок.Это можно сделать либо путем предоставления экземпляра агрегата в команде (не рекомендуется), либо путем предоставления Repository<Node> и nodeId для обработчика команды, который является самим агрегатом и также не рекомендуется.В настоящее время я не вижу правильного способа сделать это и дальше по дороге, чтобы проверить это.

Ответы [ 2 ]

0 голосов
/ 16 ноября 2018

Я думаю, @plalx ставит вас на правильный путь. Команды являются частью вашего API / Контракта на сообщения, и разоблачение Агрегата там не так уж и велика. Кроме того, я хотел бы отметить, что AggregateFixtures в Axon предназначен для тестирования одного Агрегата, а не для координации операций между Агрегатами.

Координация между агрегатами / ограниченным контекстом, как правило, там, где вы видите саги, вступающие в игру. Теперь, если честно, я немного сомневаюсь, оправдывает ли этот вариант использования Saga, но я мог бы предположить, что если ParkCarInGarageCommand завершится неудачно из-за того, что агрегат Garage заполнен (например), вам нужно указать Car Агрегируйте через другую команду, сообщая, что это не разрешено. Сага, настроенная в Axon, может помочь вам в этом, поскольку вы можете легко поймать (1) исключение из обработки команды или (2) обработать событие, уведомляющее, что операция не была успешной.

0 голосов
/ 15 ноября 2018

Я бы не помещал экземпляры AR в команды.Схемы команд должны быть стабильными и простыми для сериализации / повторной сериализации, поскольку они являются контрактами сообщений.

Вместо этого вы можете разрешить зависимость в обработчике команд.

//ParkInGarage command handler
Garage garage = garageRepository.garageOfId(command.garageId);
Car car = carRepository.carOfId(command.carId);

car.parkIn(garage);

Я не знаюAxon Framework вообще знаю, но это должно быть относительно легко проверить сейчас.

...