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

时间:2013-12-06 16:58:23

标签: scala mockito specs2

假设我有这个界面和类:

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的预期用途吗?

1 个答案:

答案 0 :(得分:14)

当您将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 {
      ...
    }