如何在 ScalaTest 中使用具有异步规范的夹具上下文对象?

ste*_*bot 5 unit-testing asynchronous scala scalatest

我正在尝试在 ScalaTest 中使用带有异步测试的夹具上下文对象

简单地将两者结合起来的幼稚方法无法编译。例如:

import org.scalatest.AsyncWordSpec

import scala.collection.GenTraversableOnce
import scala.concurrent.{ExecutionContext, Future}
import scala.math.Numeric.IntIsIntegral

trait Adder[T] {
  implicit def num: Numeric[T]
  def add(number: T): Unit
  def result: Future[T]
}

object Foo {
  def doubleSum[T](adder: Adder[T], numbers: GenTraversableOnce[T])(implicit ec: ExecutionContext): Future[T] = {
    numbers.foreach(adder.add)
    val num = adder.num
    import num._
    adder.result.map(result => result + result)
  }
}

class FooSpec extends AsyncWordSpec {

  trait IntAdder {
    val adder = new Adder[Int] {
      override implicit val num = IntIsIntegral
      private var sum = Future.successful(num.zero)
      override def add(number: Int): Unit = sum = sum.map(_ + number)
      override def result: Future[Int] = sum
    }
  }

  "Testing" should {
    "be productive" in new IntAdder {
      Foo.doubleSum(adder, Seq(1, 2, 3)).map(sum => assert(sum == 12))
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

这无法编译:

Error:(37, 11) type mismatch;
found   : FooSpec.this.IntAdder
required: scala.concurrent.Future[org.scalatest.compatible.Assertion]
          new IntAdder {
Run Code Online (Sandbox Code Playgroud)

这是一个合法的错误,但我想知道在 ScalaTest 风格中有什么方法可以解决这个问题。

我想保留夹具上下文对象,因为这允许我使用可堆叠特征模式

PH8*_*H88 3

关于什么:

import org.scalatest.compatible.Assertion

class FooSpec extends AsyncWordSpec {

  def withIntAdder(test: Adder[Int] => Future[Assertion]): Future[Assertion] = {
     val adder = new Adder[Int] { ... }
     test(adder)
  }

  "Testing" should {
    "be productive" in withIntAdder { adder =>
      Foo.doubleSum(adder, Seq(1, 2, 3)).map(sum => assert(sum == 12))
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

或者

class FooSpec extends AsyncWordSpec {

  trait IntAdder {
    val adder = new Adder[Int] {
      override implicit val num = IntIsIntegral
      private var sum = Future.successful(num.zero)
      override def add(number: Int): Unit = sum = sum.map(_ + number)
      override def result: Future[Int] = sum
    }
  }
  trait SomeMoreFixture {

  }

  "Testing" should {
    "be productive" in {
      val fixture = new IntAdder with SomeMoreFixture
      import fixture._
      Foo.doubleSum(adder, Seq(1, 2, 3)).map(sum => assert(sum == 12))
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

  • 并非所有 ScalaTest 风格都支持“fixture-context 对象”。具体来说,`AsyncWordSpec` 没有。请参阅 scaladoc http://doc.scalatest.org/3.0.0/index.html#org.scalatest.AsyncWordSpec,它未在“共享装置”部分中列出。您可以考虑在套件级别使用可堆叠特征模式(请参阅 scaladoc 中的“通过堆叠特征组合灯具”部分)和嵌套套件。否则,恐怕您必须实施自己的解决方法,就像您在自己的答案中尝试过的那样。 (3认同)