Mam kilka sytuacji, w których podrywam mnie, gdy testuję aktora, a aktor rzuca wyjątek niespodziewanie (z powodu błędu) , ale test wciąż mija. Teraz przez większość czasu wyjątek w akcie oznacza, że cokolwiek test zweryfikuje, nie wyjdzie prawidłowo, więc test się nie powiedzie, ale w rzadkich przypadkach to nieprawda. Wyjątek występuje w innym wątku niż bieg testowy, więc biegacz testowy nic o nim nie wie.Wada skalaty, gdy aktor akka zgłasza wyjątek poza wątkiem testowym
Jednym z przykładów jest użycie makiety do sprawdzenia, czy wywoływana jest jakaś zależność, a z powodu pomyłki w kodzie aktora wywołuję nieoczekiwaną metodę w sztuczce. To powoduje, że próbka rzuca wyjątek, który wysadza aktora, ale nie test. Czasami może to nawet doprowadzić do tego, że testy w nieznajomym stanie się tajemnicze z powodu sposobu, w jaki aktor wyleciał w powietrze. Na przykład:
// using scala 2.10, akka 2.1.1, scalatest 1.9.1, easymock 3.1
// (FunSpec and TestKit)
class SomeAPI {
def foo(x: String) = println(x)
def bar(y: String) = println(y)
}
class SomeActor(someApi: SomeAPI) extends Actor {
def receive = {
case x:String =>
someApi.foo(x)
someApi.bar(x)
}
}
describe("problem example") {
it("calls foo only when it receives a message") {
val mockAPI = mock[SomeAPI]
val ref = TestActorRef(new SomeActor(mockAPI))
expecting {
mockAPI.foo("Hi").once()
}
whenExecuting(mockAPI) {
ref.tell("Hi", testActor)
}
}
it("ok actor") {
val ref = TestActorRef(new Actor {
def receive = {
case "Hi" => sender ! "Hello"
}
})
ref.tell("Hi", testActor)
expectMsg("Hello")
}
}
„problemExample” przechodzi, ale potem za „ok aktor” nie dla jakiegoś powodu ja nie bardzo rozumiem ... z tym wyjątkiem:
cannot reserve actor name '$$b': already terminated
java.lang.IllegalStateException: cannot reserve actor name '$$b': already terminated
at akka.actor.dungeon.ChildrenContainer$TerminatedChildrenContainer$.reserve(ChildrenContainer.scala:86)
at akka.actor.dungeon.Children$class.reserveChild(Children.scala:78)
at akka.actor.ActorCell.reserveChild(ActorCell.scala:306)
at akka.testkit.TestActorRef.<init>(TestActorRef.scala:29)
Więc mogę zobacz sposoby złapania tego typu rzeczy, sprawdzając wyjście rejestratora w AfterEach handlers. Zdecydowanie wykonalne, choć trochę skomplikowane w przypadkach, w których naprawdę oczekuję wyjątku i właśnie to próbuję przetestować. Ale czy istnieje bardziej bezpośredni sposób radzenia sobie z tym i niepowodzenie testu?
Dodatek: Spojrzałem na TestEventListener i podejrzewam, że jest tam coś, co mogłoby pomóc, ale nie widzę tego. Jedyną dostępną dokumentacją było wykorzystanie jej do sprawdzenia oczekiwanych wyjątków, a nie nieoczekiwanych.
Dzięki za sugestie. Naprawdę chcę czegoś, co mogę złożyć w cechę zestawu testowego wielokrotnego użytku. Kiedy mam szansę, pomyślę o tym, w jaki sposób mogę wziąć jeden z tych pomysłów i pracować. – ryryguy