在测试过程中,我收到以下错误消息:
[ERROR] [07/13/2019 14:25:39.659] [DetectorSystem3-akka.io.pinned-dispatcher-2] [akka://DetectorSystem3/user/DetectorSupervisor] SapActiveConfirmed (of class com.sweetsoft.detector.ServerMonitoring$SapActiveConfirmed$)
scala.MatchError: SapActiveConfirmed (of class com.sweetsoft.detector.ServerMonitoring$SapActiveConfirmed$)
at com.sweetsoft.detector.DetectorStateMachine$.$anonfun$create$2(DetectorStateMachine.scala:20)
at akka.actor.typed.internal.BehaviorImpl$ReceiveMessageBehavior.receive(BehaviorImpl.scala:53)
at akka.actor.typed.Behavior$.interpret(Behavior.scala:437)
at akka.actor.typed.Behavior$.interpretMessage(Behavior.scala:393)
at akka.actor.typed.internal.adapter.ActorAdapter.handleMessage(ActorAdapter.scala:121)
at akka.actor.typed.internal.adapter.ActorAdapter.aroundReceive(ActorAdapter.scala:102)
at akka.actor.ActorCell.receiveMessage(ActorCell.scala:612)
at akka.actor.ActorCell.invoke(ActorCell.scala:581)
at akka.testkit.CallingThreadDispatcher.process$1(CallingThreadDispatcher.scala:280)
at akka.testkit.CallingThreadDispatcher.runQueue(CallingThreadDispatcher.scala:313)
at akka.testkit.CallingThreadDispatcher.dispatch(CallingThreadDispatcher.scala:234)
at akka.actor.dungeon.Dispatch.sendMessage(Dispatch.scala:158)
at akka.actor.dungeon.Dispatch.sendMessage$(Dispatch.scala:152)
at akka.actor.ActorCell.sendMessage(ActorCell.scala:447)
我使用的是akka型,我认为它不应该这样。
actor的实现如下:
object DetectorStateMachine {
case class State(kafka: ServerHealthEvent, sap: ServerHealthEvent)
def create(informant: ActorRef[InformantEvent]): Behavior[ServerHealthEvent] =
Behaviors.setup { context =>
context.log.info(s"=============> Start DetectorStateMachine <=============")
def loop(state: State): Behavior[ServerHealthEvent] = {
Behaviors.receiveMessage {
case KafkaActiveConfirmed
if state.kafka == KafkaActiveConfirmed || state.sap == SapActiveConfirmed =>
informant ! ServerOnlineConfirmed
loop(state)
case k@KafkaActiveConfirmed if state.kafka == KafkaInactiveConfirmed =>
loop(State(k, state.sap))
case k@KafkaInactiveConfirmed =>
informant ! ServerOfflineConfirmed
loop(State(k, state.sap))
case SapActiveConfirmed
if state.sap == SapActiveConfirmed && state.kafka == KafkaActiveConfirmed =>
informant ! ServerOnlineConfirmed
loop(state)
case s@SapActiveConfirmed if state.sap == SapInactiveConfirmed =>
loop(State(state.kafka, s))
case s@SapInactiveConfirmed =>
informant ! ServerOfflineConfirmed
loop(State(state.kafka, s))
}
}
loop(State(KafkaInactiveConfirmed, SapInactiveConfirmed))
}
}
并且该测试的实现方式为:
final class DetectorSpec extends BddSpec {
private val sap = new SapMock()
.withExposedPorts(8080)
.waitingFor(Wait.forHttp("/"))
private val kafka = new KafkaContainer("5.2.1")
sap.start()
kafka.start()
override def afterAll(): Unit = {
sap.stop()
kafka.stop()
}
private def withKafkaOfflineSapOnline(testCode: TestProbe[ServerEvent] => Unit)
: Unit = {
val config = ConfigFactory.parseString(
s"""akka.actor.default-dispatcher = {
type = akka.testkit.CallingThreadDispatcherConfigurator
}
akka.actor.testkit.typed.single-expect-default = 0s
kafka {
servers = "PLAINTEXT://localhost:9092"
}
sap {
server = "ws://${sap.getContainerIpAddress}:${sap.getMappedPort(8080)}"
}""")
val testKit = ActorTestKit("DetectorSystem3", config)
val inbox = testKit.createTestProbe[ServerEvent]("Receiver")
testKit.spawn(DetectorSupervisor.create(), "DetectorSupervisor")
testKit.system.receptionist ! Receptionist.Register(ServerStateKey, inbox.ref)
testCode(inbox)
testKit.shutdownTestKit()
}
scenario("SAP is online and Kafka is offline") {
withKafkaOfflineSapOnline { inbox =>
Given("I am waiting for the current state message")
When("I am receive the state message")
val msg = inbox.receiveMessage(60.second)
Then("it should contain `Kafka is offline`")
msg should be(ServerOfflineApproved)
}
}
}
}
我在做什么错了?
答案 0 :(得分:1)
好吧,您有两个SapActiveConfirmed
分支:
case SapActiveConfirmed
if state.sap == SapActiveConfirmed && state.kafka == KafkaActiveConfirmed =>
...
case s@SapActiveConfirmed if state.sap == SapInactiveConfirmed =>
...
因此,如果两个条件都不成立(例如state
为State(KafkaInactiveConfirmed, SapActiveConfirmed)
),那么您将获得MatchError
。 withKafkaOfflineSapOnline
当然听起来可以产生这种状态...
如果您以不同的方式构造匹配项,可能会有所帮助:
Behaviors.receiveMessage {
case KafkaActiveConfirmed =>
...
case KafkaInactiveConfirmed =>
...
...
}
条件进入分支机构的内部。
答案 1 :(得分:0)
如果要避免匹配错误-最好添加带有错误打印输出的后备空白案例