首页 > 解决方案 > Scala / Specs2 : def is(implicit ee: ExecutionEnv) = { "Service" should {...} }

问题描述

我尝试将 Scala/Play 项目升级到 Play 2.7、Scala 2.12.11、Specs2 4.5.1。

在项目中有以下 Specs2 测试,我无法理解它的 Specs2 规范结构(可能是自编写测试以来 Specs2 API 发生了很大变化)。

当我查看当前 API中的规范结构时,我看不到任何is方法与should.

它应该是什么意思?

如何在当前的 Specs2 API 中重写这样的规范?

我还注意到,在使用该方法时,应该使用测试代码import org.specs2.mutable.Specification而不是import org.specs2.Specification应该使用的测试代码。is它使用def is(implicit ee: ExecutionEnv), 而不是def is.

这是旧的测试:

package services

import org.specs2.concurrent.ExecutionEnv
import org.specs2.mutable.Specification
import org.specs2.specification.mutable.ExecutionEnvironment
import play.api.inject.guice.GuiceApplicationBuilder
import play.api.test.WithApplication
import play.modules.reactivemongo._

import scala.concurrent.duration._

class StatisticsServiceSpec() extends Specification with ExecutionEnvironment {

  def is(implicit ee: ExecutionEnv) = {
    "The StatisticsService" should {

      "compute and publish statistics" in new WithApplication() {
        val repository = new MongoStatisticsRepository(configuredAppBuilder.injector.instanceOf[ReactiveMongoApi])
        val wsTwitterService = new WSTwitterService
        val service = new DefaultStatisticsService(repository, wsTwitterService)

        val f = service.createUserStatistics("elmanu")

        f must beEqualTo(()).await(retries = 0, timeout = 5.seconds)
      }

    }

    def configuredAppBuilder = {
      import scala.collection.JavaConversions.iterableAsScalaIterable

      val env = play.api.Environment.simple(mode = play.api.Mode.Test)
      val config = play.api.Configuration.load(env)
      val modules = config.getStringList("play.modules.enabled").fold(
        List.empty[String])(l => iterableAsScalaIterable(l).toList)

      new GuiceApplicationBuilder().
        configure("play.modules.enabled" -> (modules :+
          "play.modules.reactivemongo.ReactiveMongoModule")).build
    }
  }

}

为了将代码简化为实际的 Specs2 API,我认为可以将其简化为以下内容:

package services

import org.specs2.concurrent.ExecutionEnv
import org.specs2.mutable.Specification

import scala.concurrent.Future
import play.api.test.WithApplication

import scala.concurrent.duration._

class StatisticsServiceSpec(implicit ee: ExecutionEnv) extends Specification /* with ExecutionEnvironment */ {

  def is(implicit ee: ExecutionEnv) = {

    "The StatisticsService" should {

      "compute and publish statistics" in new WithApplication() {

        val f = Future(1)

        f must beEqualTo(1).await(retries = 0, timeout = 5.seconds)
      }
    }
  }
}

请注意我删除了该ExecutionEnvironment特征,因为它似乎已从库中删除。

现在,代码终于编译了,但是当我尝试运行测试时,没有错误,但实际上没有运行测试:输出为Empty test suite.

标签: scalaplayframeworkspecs2

解决方案


新规范应该是

package services

import org.specs2.concurrent.ExecutionEnv
import org.specs2.mutable.Specification

import scala.concurrent.Future
import play.api.test.WithApplication

import scala.concurrent.duration._

class StatisticsServiceSpec(implicit ee: ExecutionEnv) extends Specification {
  "The StatisticsService" should {
    "compute and publish statistics" in new WithApplication() {
      val f = Future(1)
      f must beEqualTo(1).await(retries = 0, timeout = 5.seconds)
    }
  }
}

现在ExecutionEnv真的应该直接作为规范成员检索(并implicit使其可用于await方法)。

is在“可变”规范中不是必需的。is是 a 中的函数Specification,您在其中声明规范的所有“片段”(aFragment是 a Description+ an Execution)。在可变规范中,当规范被实例化时,您直接在类的主体中触发方法调用这一事实会自动填充此函数。由创建的片段并被should收集in在一个可变变量中,因此得名“可变规范”。

如果您定义def is(implicit ee: ExecutionEnv),这就像定义isspecs2 不知道的另一个有效定义,而不为该def is: Fragments方法创建任何内容。这就是为什么你最终得到一个空的规范。


推荐阅读