我最近在项目中添加了对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(或具有apply方法)。
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
最佳答案
编辑-根据下面的Eric的评论,这是Specs2≤1.12.2中的错误。应在1.12.3中修复。
事实证明,Specs2重新定义了Mockito中的某些行为,以便获得匹配的按名称参数。
Eric answered my question
“我不喜欢这样,但这是我发现按姓名匹配的唯一方法
参数:http://bit.ly/UF9bVC。您可能想要那个。”
从Specs2文档中
Byname
可以验证Byname参数,但是如果specs2不能使用
jar不放在模拟路径jar之前的类路径上。确实
specs2重新定义了Mockito类来拦截方法调用,以便
正确处理byname参数。
为了使我的测试再次通过,我做了与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