TL;博士:
我不知道如何在不保证消息顺序的情况下测试 Akka actor 是否接收到一组不同类型的消息。
规格:
我正在测试一些域事件是否发布到akka.event.EventStream
. 为此,我订阅了TestProbe
所有DomainEvent
子类:
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)
}
}
}
}
谢谢!