Перепроектирование зависимостей
На мой взгляд, самым большим недостатком вашего текущего дизайна является то, что существует внутренняя зависимость от конкретного actorSystem
;ошибочная строка кода:
//actorSystem comes from the outside world!!!
val notificationActor = actorSystem.actorOf(NotificationActor.props(userName, jsonHelper))
Метод notificationClientFlow
должен быть перепараметрирован, чтобы все зависимости были явно указаны в аргументе.И не должно быть зависимости от всего ActorSystem
, вместо этого она должна быть уменьшена до ActorRef
:
def notificationClientFlow(userName: String,
notificationActor : ActorRef): Flow[Message, Message, NotUsed] = {
//notificationActor is now passed in
//val notificationActor = actorSystem.actorOf(NotificationActor.props(userName, jsonHelper))
}
Это потребует аналогичного явного объявления в методе создания Route
:
private def loginNotificationRoute(notificationActor : ActorRef)() : Route = {
...
handleWebSocketMessages(notificationClientFlow(userName, notificationActor))
}
Тестирование
Теперь тестирование можно выполнить с помощью TestKit
:
class MySpec() extends TestKit(ActorSystem("MySpec")) {
val userName = "testUser"
val notificationActor =
system.actorOf(NotificationActor.props(userName, jsonHelper))
val testFlow = notificationClientFlow(userName, notificationActor)
}
Такжепоскольку мы явно передали ActorRef
, а не только ActorSystem
, мы можем использовать другие расширенные функции тестирования, такие как зонды :
val probe = TestProbe()
val testProbeFlow = notificationClientFlow(userName, probe.ref)
Вышеупомянутая методика аналогично применима ктестирование маршрута с использованием стандартных методик :
val testRoute = loginNotificationRoute(testProbe)
Get() ~> testRoute() ~> check {
//testing assertions here
}