为什么这个specs2测试使用Mockito通过



假设我有这个接口和类:

abstract class SomeInterface{
  def doSomething : Unit
}
class ClassBeingTested(interface : SomeInterface){
  def doSomethingWithInterface : Unit = {
    Unit
  }
}

请注意,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
      }
    }
  }
}

此测试通过。为什么?我设置错了吗?

当我摆脱范围:

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
      }
    }
  }
}

测试按预期失败:

[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();

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

当您将Mockito特征与另一个特征混合时,您可以创建类似there was one(interface).doSomething的期望值。如果这样的表达式失败,它只返回Result,而不会抛出Exception。然后它会在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)
      }
      ...
    }
    
  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 {
      ...
    }
    

相关内容

  • 没有找到相关文章