TL;DR:
メッセージの順序を保証せずに、Akka アクターがさまざまな種類のメッセージのセットを受信することをテストする方法がわかりません。
仕様:
一部のドメイン イベントが に公開されることをテストしていますakka.event.EventStream
。TestProbe
そうするために、すべてのDomainEvent
サブクラスにa をサブスクライブしました。
val eventBusTestSubscriber = TestProbe()(actorSystem)
actorSystem.eventStream.subscribe(eventBusTestSubscriber.ref, classOf[DomainEvent])
このようにして、他の可能性のあるイベントを考慮せずに、単一のドメイン イベントが に到着することをテストできます (脆弱なテストは避けてください)。EventStream
仕様:
shouldPublishDomainEvent {
event: WinterHasArrivedDomainEvent =>
event.isReal shouldBe true
event.year shouldBe expectedYear
}
ヘルパー特性:
def shouldPublishDomainEvent[EventType](eventAsserter: EventType => Unit)
(implicit gotContext: GotContextTest, classTag: ClassTag[EventType]): Unit = {
val receivedEvent = gotContext.eventBusTestSubscriber.receiveN(1).head
receivedEvent match {
case event: EventType =>
eventAsserter(event)
case _ =>
shouldPublishDomainEvent(eventAsserter)
}
}
また、他の可能なイベントを考慮せずに順序を保証する同じタイプのイベントのセットを受け取る必要があるシナリオのテストもあります (脆弱なテストは避けてください)。
仕様:
val someoneDiedEventAsserter: SomeoneDiedDomainEvent => Unit = { event =>
event.isReal shouldBe false
event.episodeId shouldBe episodeId
}
val someoneDiedEventIdExtractor = (event: SomeoneDiedDomainEvent) => event.characterId
shouldPublishDomainEventsOfType(someoneDiedEventAsserter, someoneDiedEventIdExtractor)(characterIdsToDie)
ヘルパー特性:
def shouldPublishDomainEventsOfType[EventType, EventIdType](
eventAsserter: EventType => Unit,
eventIdExtractor: EventType => EventIdType
)(expectedEventIds: Set[EventIdType])
(implicit gotContext: GotContextTest, classTag: ClassTag[EventType]): Unit = {
if (expectedEventIds.nonEmpty) {
val receivedEvent = gotContext.eventBusTestSubscriber.receiveN(1).head
receivedEvent match {
case event: EventType =>
eventAsserter(event)
val receivedEventId = eventIdExtractor(event)
expectedEventIds should contain(receivedEventId)
shouldPublishDomainEventsOfType(eventAsserter, eventIdExtractor)(expectedEventIds - receivedEventId)
case _ =>
shouldPublishDomainEventsOfType(eventAsserter, eventIdExtractor)(expectedEventIds)
}
}
}
問題は、さまざまなタイプの一連のイベントを公開しており、順序が保証されていないことをテストする必要があるユース ケースにあります。
私が解決する方法がわからない問題は、このshouldPublishDomainEventsOfType
場合、EventType
この非常に特定のタイプに関連する特定のアサーションをeventAsserter: EventType => Unit
. しかし、私はさまざまな特定のタイプのイベントを持っているため、それらのタイプなどを指定する方法がわかりません。
アサーション関数を含むケース クラスに基づくアプローチを試みましたが、問題は同じで、少し行き詰まっています。
case class ExpectedDomainEvent[EventType <: DomainEvent](eventAsserter: EventType => Unit)
def shouldPublishDomainEvents[EventType](
expectedDomainEvents: Set[ExpectedDomainEvent]
)(implicit chatContext: ChatContextTest): Unit = {
if (expectedDomainEvents.nonEmpty) {
val receivedEvent = chatContext.eventBusTestSubscriber.receiveN(1).head
expectedDomainEvents.foreach { expectedDomainEvent =>
val wasTheReceivedEventExpected = Try(expectedDomainEvent.eventAsserter(receivedEvent))
if (wasTheReceivedEventExpected.isSuccess) {
shouldPublishDomainEvents(expectedDomainEvents - receivedEvent)
} else {
shouldPublishDomainEvents(expectedDomainEvents)
}
}
}
}
ありがとう!