как получить значение будущего в Asyn c способом в scala тесте с использованием набора тестов akka - PullRequest
0 голосов
/ 12 марта 2020

я использую akka testkit и скалярные программы для запуска моего теста, вот мой код

class MyTest extends (ActorSystem("testsystem")) /*with AsyncWordSpec*/ with ImplicitSender with AnyWordSpecLike  with Matchers with BeforeAndAfterAll {
   "an actor test" must {
      val probe = TestProbe()
      val myActor1 = TestActorRef[MyActor]

      "send back messages " in {
        probe.send(myActor1,Found(id = "234"))
        probe.expectMsg(true)
        //i want to get the future value like this as well 
        val future = ask(myActor, Found(id = "234")).mapTo[Boolean]
        future onComplete {
            case Success(somevalue) => info("oncomplete returned result is " + somevalue)
            case Failure(ex) =>throw ex
        }
    }
}

class MyActor extends Actor {

  def receive: PartialFunction[Any, Unit] = {
    case Found(id) => 
      log.info("received message {}", id)
      sender() ! true
    case message =>
      unhandled(message)
  }
}

сейчас проблема в том, что приведенный выше код работает нормально, но будущее для полной части когда-нибудь выполняется, а иногда нет при запуске теста для этого я исследовал об асин c тестирования scala и попытаться реализовать примеры http://www.scalatest.org/user_guide/async_testing

для этого мне нужно расширить с любой из заданных классов я выбрал AsyncWordSpec, чтобы я мог запускать асин c тесты и каждый раз получать значение в будущем, но я уже расширяюсь от TestKit класса, я не могу расширяться от абстрактного класса AsyncWordSpec так как я могу заставить это работать?

Ответы [ 2 ]

0 голосов
/ 23 марта 2020

Некоторые пояснения:

Блокировка отдельного потока, выполняющего тест, пока не завершится будущее, в порядке, в тестовом примере нет значения asyn c. Тестовый поток отделен от потоков / диспетчеров в Akka, где было бы проблематично c блокировать.

Блокировка при завершении - это то, что тесты TestKit делают, когда вы, например, expectMessage. Await.result - это один из способов, Scalatest также имеет ScalaFutures, который добавляет декоратор к Future с именами .futureValue и .whenReady, оба они также блокируют тестовый поток, пока не завершится будущее или не истечет тайм-аут.

0 голосов
/ 12 марта 2020

Проблема в том, что ваш future нужно ждать, чтобы убедиться, что он выполняется. Фьючерсы начинают оценку в момент создания асинхронно. Это означает, что основной поток не будет заблокирован до будущего завершения - он продолжит работу. Итак, в вашем случае есть две возможности:

1)
test start
|
|_ _ _ _ _ _ _ _
future creation  \
|                |
|                | 
|                future completed, callback executed
test end
2) 

test start
|
|_ _ _ _ _ _ _ _ _ 
future creation   \
|                 |
|                 | 
|                 |
test end          |
executor shutdown X - future termination, no callback

Во втором случае ваш обратный вызов не запускается из-за будущего завершения при выходе из теста. Чтобы сделать это более предсказуемым, вы должны заблокировать свое будущее в конце теста. Вы можете сделать это с помощью тестового фреймворка Sugar или Await.result.

...