Каков наилучший способ утверждения метода scala, тип возвращаемого значения которого - Future [Unit] - PullRequest
0 голосов
/ 06 июля 2018

У меня есть метод. Этот метод может возвращать Future.failed (.....) или Future.successful (()).

def вычислить (x: Int, y: Int): Future [Unit] = { ........ }

Теперь мне нужно проверить этот метод. Каков наилучший способ утверждать для теста, который проверяет Future.successful(()) case.

Ответы [ 3 ]

0 голосов
/ 06 июля 2018

Scalatest предлагает несколько способов работы с Future с.

Вариант 1: isReadyWithin

import org.scalatest.concurrent.ScalaFutures._
import scala.concurrent.duration._

calculate(1, 3).isReadyWithin(1.second) should be(true)

Если вы хотите что-то сделать с некоторым возвращаемым значением, вы можете использовать whenReady:

implicit val patienceConfig = PatienceConfig(1.second)

def calculateWithResult(i: Int, j: Int): Future[Int] = ???

whenReady(calculateWithResult(1,3)) { result =>
    result should be(4)
}

Вам нужен неявный PatienceConfig в области видимости, который сообщает whenReady, когда не пройден тест из-за тайм-аута. Я полагаю, что в одной из библиотек scalatest есть одна по умолчанию, но выбранный период времени довольно короткий - порядка 10 миллисекунд - и может часто вызывать нестабильные тесты.

Вариант 2: AsyncXSpec

Существует Async разновидностей FlatSpec, FreeSpec, FunSpec и т. Д. Они работают так же, как и их синхронные варианты, за исключением того, что любой тест должен теперь возвращать значение типа Future[Assertion]. Например:

class Test extends AsyncFreeSpec {
  "An asynchronous method" - {
    "should succeed" in {
      calculate(1,3).map { _ =>
        // just want to make sure the future completes
        succeed
      }
    }
  }
}

Опять же, вы можете запустить тест на результат здесь. Обратите внимание, что этот вариант означает, что каждый тест в вашем тестовом классе должен возвращать Future, так что это не очень хорошо, если вы хотите смешать синхронные и асинхронные тесты. Я также, честно говоря, не уверен, как AsyncXSpec выбирает значение времени ожидания.

Опция Не: Await.result

Я бы рекомендовал не использовать Await.result, поскольку он блокирует поток на время. Насколько мне известно, две вышеупомянутые опции разработаны таким образом, чтобы асинхронные тесты можно было легко выполнять параллельно.

Предостережения:

Вы хотите быть очень осторожными со своими тайм-аутами при выполнении асинхронного тестирования. Слишком долго, и ваши тесты могут закончиться целую вечность, если что-то пойдет не так. Слишком короткий, и ваши тесты будут ненадежными. И программа может работать по-разному в разных средах, поэтому вы можете обнаружить, что время ожидания, достаточное для вашей локальной машины, приводит к сбою тестов на сервере сборки в 5% случаев. Будьте осторожны!

0 голосов
/ 06 июля 2018

Я предполагаю, что вы уже продлили ScalaFutures в тестовом классе, и вы настроили время ожидания (patienceConfig) в соответствии со своими потребностями. Если вы сделали это, то можете использовать один из следующих подходов:

whenReady(calculate(1,3))(_ => succeed)

или

whenReady(calculate(1,3))(_ shouldBe ())

Первый подход предпочтительнее, так как не может быть никакого другого значения для Unit, поэтому нам не нужно явно проверять его, если код по какой-то причине не возвращает null.

0 голосов
/ 06 июля 2018

Как минимум два варианта:

  • Вы можете либо Await.result, а затем убедиться, что результат соответствует ожиданиям, заявив что-то об этом.
  • Вы можете делать свои утверждения внутри самого будущего, но затем использовать что-то вроде AsyncFlatSpec для своих тестов.
...