Я тестирую свои обработчики команд как-то так:
public function testHandle_ShouldPublishFooEvent(): void
{
$fooCommand = $this->givenFooCommand();
$this->whenHandleCommand($fooCommand);
$this->thenFooEventIsPublished();
}
По сути, я тестирую только счастливый сценарий, когда в обработчике команд отсутствует логика проверки. Я проверяю это, проверяя, что ожидаемое событие было опубликовано в шине событий. Перед отправкой проверенной команды в командную шину в методе whenHandleCommand я начинаю записывать отправленные события, что-то вроде:
$eventBus->attach(
EventBus::EVENT_DISPATCH,
function (ActionEvent $actionEvent) use ($events): void {
$event = $actionEvent->getParam(MessageBus::EVENT_PARAM_MESSAGE);
$events->addEvent($event);
},
-1000
);
и в конце я просто проверяю записанные события и утверждаю, что это то, что я ожидал. Но у меня проблема с переключением между MysqlEventStore
а также InMemoryEventStore
, так как MysqlEventStore
не является транзакционным (и, следовательно, saveAggregateRoot
метод), а не InMemoryEventStore
это транзакция (и, следовательно, передача событий в методе коммитов).
Мой метод сохранения в хранилище так же прост:
class ProophFooRepository extends AggregateRepository implements FooRepository
{
public function save(FooAggregate $foo): void
{
$this->saveAggregateRoot($foo);
}
...
}
Как сделать так, чтобы я мог изменить любое хранилище событий (память или pdo), которое я хочу использовать, и оно будет работать? Должен ли я иметь условие if($this->isTransactionalEventStore())
(затем начать транзакцию и зафиксировать) в моем хранилище для этого? Мне это не нравится 🙁
Почему существует только InMemoryEventStore, который является транзакционным? Не должно быть лучше иметь оба InMemoryTransactionalEventStore
а также InMemoryEventStore
? Потому что я хочу, чтобы мои тесты запускались с InMemoryEventStore, в то время как обычно я использую PdoEventStore.
РЕДАКТИРОВАТЬ: Когда я изменяю строку 100 в InMemoryEventStoreFactory на
$wrapper = new ActionEventEmitterEventStore($eventStore, $eventEmitter);
и сделать InMemoryEventStore
инвентарь EventStore
вместо TransactionalEventStore
, все работает просто отлично. Так что либо я как-то не правильно использую prooph и это не нужно, либо это можно исправить с помощью PR с помощью расщепления. ImMemoryEventStore
в InMemoryTransactionalEventStore
а также InMemoryEventStore
?
Это очень правильный вопрос. Проблема в том, что я не думал об этом сценарии использования при работе с реализацией хранилища событий v7. Обходной путь — обернуть с помощью ActionEventEmitterEventStore, как вы описали. Однако нетранзакционный в хранилище событий памяти будет лучшей альтернативой (которой нет в данный момент).
В настоящее время InMemoryEventStore является транзакционным, поэтому удаление этой функциональности и помещение ее в TransactionalInMemoryEventStore было бы разрывом BC, что мы не можем сделать без новой основной версии. Вот почему я думаю, что мы должны создать новую реализацию под названием NonTransactionalInMemoryEventStore. Я создал билет здесь: https://github.com/prooph/event-store/issues/307. Хотите взять это на себя и обеспечить пиар?
Других решений пока нет …