1

TL;DR:

メッセージの順序を保証せずに、Akka アクターがさまざまな種類のメッセージのセットを受信することをテストする方法がわかりません。

仕様:

一部のドメイン イベントが に公開されることをテストしていますakka.event.EventStreamTestProbeそうするために、すべての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)
      }
    }
  }
}

ありがとう!

4

1 に答える 1