为什么这个specs2测试使用Mockito传递?

mus*_*oom 9 scala mockito specs2

假设我有这个接口和类:

abstract class SomeInterface{
  def doSomething : Unit
}

class ClassBeingTested(interface : SomeInterface){
  def doSomethingWithInterface : Unit = {
    Unit
  }
}
Run Code Online (Sandbox Code Playgroud)

请注意,doSomethingWithInterface方法实际上不对接口执行任何操作.

我为它创建了一个测试:

import org.specs2.mutable._
import org.specs2.mock._
import org.mockito.Matchers
import org.specs2.specification.Scope

trait TestEnvironment extends Scope with Mockito{
  val interface = mock[SomeInterface]
  val test = new ClassBeingTested(interface)
}

class ClassBeingTestedSpec extends Specification{
  "The ClassBeingTested" should {
    "#doSomethingWithInterface" in {
      "calls the doSomething method of the given interface" in new TestEnvironment {
        test.doSomethingWithInterface
        there was one(interface).doSomething
      }
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

这个测试通过.为什么?我设置错了吗?

当我摆脱范围:

class ClassBeingTestedSpec extends Specification with Mockito{
  "The ClassBeingTested" should {
    "#doSomethingWithInterface" in {
      "calls the doSomething method of the given interface" in {
        val interface = mock[SomeInterface]
        val test = new ClassBeingTested(interface)
        test.doSomethingWithInterface
        there was one(interface).doSomething
      }
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

测试按预期失败:

[info]   x calls the doSomething method of the given interface
[error]      The mock was not called as expected: 
[error]      Wanted but not invoked:
[error]      someInterface.doSomething();
Run Code Online (Sandbox Code Playgroud)

这两个测试有什么区别?为什么第一个应该失败时通过?这不是Scopes的预期用途吗?

Eri*_*ric 14

当你将Mockito特质混合到另一个特性时,你就可以创造出类似的期望there was one(interface).doSomething.如果这样的表达式失败,它只返回一个Result,它不会抛出一个Exception.然后它会在a中迷失,Scope因为它只是一个特征体内的"纯粹"值.

但是,如果将Mockito特征混合到一个mutable.Specification异常,则会在失败时抛出异常.这是因为mutable.Specification该类指定应ThrownExpectations混合该特征.

因此,如果您想要创建一个延伸两者的特征,Scope您可以:

  1. 从规范内部创建特征,而不是扩展Mockito:

    class MySpec extends mutable.Specification with Mockito {
      trait TestEnvironment extends Scope {
        val interface = mock[SomeInterface]
        val test = new ClassBeingTested(interface)
      }
      ...
    }
    
    Run Code Online (Sandbox Code Playgroud)
  2. 像你一样创造特质和规格,但混合 org.specs2.execute.ThrownExpectations

    trait TestEnvironment extends Scope with Mockito with ThrownExpectations {
      val interface = mock[SomeInterface]
      val test = new ClassBeingTested(interface)
    }
    
    class MySpec extends mutable.Specification with Mockito {
      ...
    }
    
    Run Code Online (Sandbox Code Playgroud)