Why is this specs2 test using Mockito passing?

mockito, scala, specs2

Solution

When you mix-in the `Mockito` trait to another trait you can create expectations like `there was one(interface).doSomething`. If such an expression fails it only returns a `Result`, it doesn't throw an `Exception`. It then gets lost in a `Scope` because it is just a "pure" value inside the body of a trait.

However if you mix-in the `Mockito` trait to a `mutable.Specification` then an exception will be thrown on a failure. This is because the `mutable.Specification` class specifies that there should be `ThrownExpectations` by mixing in that trait.

So if you want to create a trait extending both `Scope` you can either:

create the trait from inside the specification and not have it extend Mockito:

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

create trait and specification as you do, but mix-in `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 {
  ...
}

Problem

Suppose I had this interface and class: ``` abstract class SomeInterface{ def doSomething : Unit } class ClassBeingTested(interface : SomeInterface){ def doSomethingWithInterface : Unit = { Unit } } ``` Note that the doSomethingWithInterface method does not actually do anything with the interface. I create a test for it like this: ``` 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 } } } } ``` This test passes. Why? Am I setting it up wrong? When I get rid of the scope: ``` 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 } } } } ``` The test fails as expected: ``` [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(); ``` What is the difference between these two tests? Why does the first one pass when it should fail? Is this not an intended use of Scopes?

Original source