3

我最近在一个项目中添加了对 Specs2 的依赖,并注意到一些使用 ScalaTest 和 Mockito 编写的现有测试失败了。删除 Specs2 后,这些测试再次通过。为什么会这样?

lazy val scalatestandspecscoexisting = Project(
  id = "scalatest-and-specs-coexisting",
  base = file("."),
  settings = Project.defaultSettings ++
    GraphPlugin.graphSettings ++
    Seq(
    name := "Scalatest-And-Specs-Coexisting",
    organization := "com.bifflabs",
    version := "0.1",
    scalaVersion := "2.9.2",
//  libraryDependencies ++= Seq(scalaTest, mockito)   //Tests Pass, no-specs2
    libraryDependencies ++= Seq(scalaTest, specs2, mockito)  //Tests Fail
  )
)

失败的测试都使用了 Mockito,并且都设置了一个带有两个不同参数的模拟方法。对模拟的调用之一不返回它设置的值。下面的例子失败了。进一步的要求是类型必须是 Function1 (或具有应用方法)。

import org.scalatest.FunSuite
import org.scalatest.mock.MockitoSugar
import org.mockito.Mockito.when

trait MockingBird {
  //Behavior only reproduces when input is Function1
  def sing(input: Set[String]): String
}

class MockSuite extends FunSuite with MockitoSugar {

  val iWannaRock = Set("I wanna Rock")
  val rock = "Rock!"

  val wereNotGonnaTakeIt = Set("We're not gonna take it")
  val no = "No! We ain't gonna take it"

  test("A mock should match on parameter but isn't") {

    val mockMockingBird = mock[MockingBird]
    when(mockMockingBird.sing(iWannaRock)).thenReturn(rock)
    //Appears to return this whenever any Set is passed to sing
    when(mockMockingBird.sing(wereNotGonnaTakeIt)).thenReturn(no)

    // Succeeds because it was set up last
    assert(mockMockingBird.sing(wereNotGonnaTakeIt) === no)
    // Fails because the mock returns "No! We ain't gonna take it"
    assert(mockMockingBird.sing(iWannaRock) === rock)
  }
}

输出:

 [info] MockSuite:
 [info] - A mock should match on parameter but isn't *** FAILED ***
 [info]   "[No! We ain't gonna take it]" did not equal "[Rock!]" (MockSuite.scala:38)
 [error] Failed: : Total 1, Failed 1, Errors 0, Passed 0, Skipped 0
4

1 回答 1

2

编辑- 根据下面 Eric 的评论,这是 Specs2 ≤ 1.12.2 中的一个错误。应该在 1.12.3 中修复。

事实证明,Specs2 重新定义了 Mockito 中的一些行为,以便获得要匹配的按名称参数。

埃里克回答了我的问题

“我不喜欢这个,但这是我发现匹配别名参数的唯一方法:http: //bit.ly/UF9bVC。你可能想要那个。”

来自 Specs2 文档

按名字

可以验证 Byname 参数,但如果 specs2 jar 没有放在类路径的第一个,在 mockito jar 之前,这将不起作用。实际上,specs2 重新定义了一个 Mockito 类来拦截方法调用,以便正确处理别名参数。

为了让我的测试再次通过,我做了与 specs2 文档中建议相反的操作,并在 Mockito之后添加了 Specs2 依赖项。我没有尝试过,但我希望按名称参数匹配失败。

lazy val scalatestandspecscoexisting = Project(
  id = "scalatest-and-specs-coexisting",
  base = file("."),
  settings = Project.defaultSettings ++
    GraphPlugin.graphSettings ++
    Seq(
    name := "Scalatest-And-Specs-Coexisting",
    organization := "com.bifflabs",
    version := "0.1",
    scalaVersion := "2.9.2",
//  libraryDependencies ++= Seq(scalaTest, mockito)   //Tests Pass
    libraryDependencies ++= Seq(scalaTest, mockito, specs2)  //Tests Pass
//  libraryDependencies ++= Seq(scalaTest, specs2, mockito)  //Tests Fail
  )
)

我的测试现在通过了

[info] MockSuite:
[info] - A mock should match on parameter but isn't
[info] Passed: : Total 1, Failed 0, Errors 0, Passed 1, Skipped 0
于 2012-11-01T02:58:07.060 回答