2016-04-14 26 views
1

TL; DR:测试,一个阿卡演员收到了一组不同类型的消息不保证顺序

我不知道如何测试一个阿卡演员收到了一组不同类型的消息,而不保证消息的顺序。

具体细节:

我测试的是某一领域的事件被发布到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) 
    } 
    } 
} 

现在的问题是在我所到t用例我认为我发布了一系列不同类型的活动,没有订单保证

我不知道如何解决的问题是,在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) 
     } 
    } 
    } 
} 

谢谢!

回答

0

解决由于Artur Soler :)

在这里,你有解决方案,以防万一它有助于任何人:

case class ExpectedDomainEventsOfType[EventType <: DomainEvent, EventId](
    eventAsserter: EventType => Unit, 
    eventIdExtractor: EventType => EventId, 
    expectedEventIds: Set[EventId] 
)(implicit expectedEventTypeClassTag: ClassTag[EventType]) { 

    def isOfEventType(event: DomainEvent): Boolean = expectedEventTypeClassTag.runtimeClass.isInstance(event) 

    def withReceivedEvent(event: DomainEvent): ExpectedDomainEventsOfType[EventType, EventId] = event match { 
    case asExpectedEventType: EventType => 
     eventAsserter(asExpectedEventType) 

     val eventId = eventIdExtractor(asExpectedEventType) 
     expectedEventIds should contain(eventId) 

     copy(expectedEventIds = expectedEventIds - eventId) 
    } 
} 

def shouldPublishDomainEvents(
    expectedEvents: Set[ExpectedDomainEventsOfType[_, _]] 
)(implicit gotContext: GotContextTest): Unit = { 

    if (expectedEvents.nonEmpty) { 
    val receivedEvent = gotContext.eventBusTestSubscriber.receiveN(1).head.asInstanceOf[DomainEvent] 

    expectedEvents.find(expectedEventsOfType => expectedEventsOfType.isOfEventType(receivedEvent)) match { 
     case Some(expectedEventsOfReceivedType) => 
     val expectedEventsWithoutTheReceived = expectedEventsOfReceivedType.withReceivedEvent(receivedEvent) 

     if (expectedEventsWithoutTheReceived.expectedEventIds.isEmpty) { 
      shouldPublishDomainEvents(expectedEvents - expectedEventsOfReceivedType) 
     } else { 
      shouldPublishDomainEvents(expectedEvents - expectedEventsOfReceivedType + expectedEventsWithoutTheReceived) 
     } 

     case None => 
     shouldPublishDomainEvents(expectedEvents) 
    } 
    } 
}