My favorites | Sign in
Logo
                
Search
for
Updated Nov 05, 2009 by etorreborre
UsingMockito  
Using Mockito mocks and stubs.

Introduction

Mockito is a mocking library which "lets you write beautiful tests with clean & simple API".

specs integrates Mockito expectations and add some syntactic sugar for an even simpler experience of Mockito.

Usage

In order to use Mockito mocks in your specification, you need to mix in the Mockito trait.

  import org.specs.Specification
  import org.specs.mock.Mockito
  import org.mockito.Matchers._  // to use matchers like anyInt()

  object spec extends Specification with Mockito {
    
    val m = mock[java.util.List[String]] // a concrete class would be mocked with: mock(new java.util.LinkedList[String])
    
    // stub a method call with a return value
    m.get(0) returns "one"
  
    // call the method
    m.get(0)
  
    // verify that the call happened, this is an expectation which will throw a FailureException if that is not the case
    m.get(0) was called
    
    // we can also check that another call did not occur
    m.get(1) wasnt called // or m.get(1) was notCalled
                          
  }

Stubbing

Stubbing values is as simple as calling a method on the mock and declaring what should be returned or thrown:

  m.get(1) returns "one"
  m.get(2) throws new Exception("forbidden")

You can specify different consecutive returned values by appending thenReturns or thenThrows:

  m.get(1) returns "one" thenReturns "two"
  m.get(2) throws new Exception("forbidden") thenReturns "999"

Smart mocks

Mocks can be made to return "smart" null values (look at setting smart return values for more details):

  trait Hello {
    def get(i: Int) = "hello"
  }
  val m = smartMock[Hello]
  m.get(0) must ==("") // instead of null

Note: there is an internal Mockito bug when doing the same thing on java.util.ListString

Argument matchers

The built-in Mockito argument matchers can be used to specify the method arguments for stubbing:

   mockedList.get(anyInt()) returns "element"
   mockedList.get(999) must_== "element"

Hamcrest matchers can also be used, allowing to create your own Hamcrest matchers:

   // stubbing using hamcrest (let's say IsNull returns your own hamcrest matcher):
   mockedList.contains(argThat(new IsNull)) returns true

While Mockito matchers are pretty exhaustive, for convenience a any[T] matcher is available:

   // the any matcher calls the org.mockito.Matchers.isA(classOf[T]) method
   mockedList.contains(any[String]) was called

You can even pass specs matchers directly as arguments where the implicit conversion would work:

   mockedList.get(==(123)) returns "one" // ==(_) is an alias for beEqualTo(_)

   // note that the implicit conversion transforming a specs Matcher to a Hamcrest matcher would not work here as the expected type for the contains method is Object
   mockedList.contains(isNull) returns true

Callbacks

In some rare cases, it is necessary to have the return value depend on the parameters passed to the mocked method:

   val mockedList = mock[List[String]]
   
   mockedList.get(anyInt) answers { i => "The parameter is " + i.toString } 
 }

The function passed to answers will be called with each parameter passed to the stubbed method:

  // returns The parameter is 0
  s.mockedList.get(0)

  // The second call returns a different value: The parameter is 1
  s.mockedList.get(1) 

Parameters for the answers function

Because of the use of reflection the function passed to answers will receive only instances of the java.lang.Object type.

More precisely, it will:

Verification

By default Mockito doesn't expect any method to be called. However if your writing interaction-based specifications you want to specify that some methods are indeed called:

  mockedList.get(0)

  mockedList.get(0) was called
  mockedList.get(1) wasnt called
  mockedList.get(2) was notCalled

If anything fails a new FailureException will be thrown creating a failure for the current example.

Constraints on call expectations

You can be more precise when specifying the number of calls on a mock:

  val mockedList = mock[List[String]]

  mockedList.add("one")
  2.times { i => mockedList.add("two") } 
  3.times { i => mockedList.add("three") } 
  
  mockedList.add("one") was called.once
  mockedList.add("two") was called.twice
  mockedList.add("two") was called.atLeastOnce
  // fails with The method was not called as expected: list.add("one"); Wanted 2 times but was 1
  mockedList.add("one") was called.twice

  // It is also possible to check that there are no unexpected calls on a mock:
  mockedList had noMoreCalls

Order of calls

The order of method calls can be checked by creating calls and chaining them with then:

  val m1 = mock[List[String]]
  val m2 = mock[List[String]]

  m1.get(0)
  m1.get(0)
  m2.get(0)

  // mock calls
  theMethod(m1.get(0)).on(m1).twice then
  theMethod(m2.get(0)).on(m2)       were called.inOrder

The implicit definition can also be removed but additional parenthesis are needed:

     (m1.get(0) on m1).twice then
     (m2.get(0) on m2)       were calledInOrder // alias for called.inOrder

Spies

Spies can also be used in order to do some "partial mocking" of real objects:

   val spiedList = spy(new LinkedList[String])

   // methods can be stubbed on a spy
   spiedList.size returns 100

   // other methods can also be used
   spiedList.add("one")
   spiedList.add("two") 
   
   // and verification can happen on a spy
   spiedList.add("one") was called

However, working with spies can be tricky:

  // if the list is empty, this will throws an IndexOutOfBoundsException
  spiedList.get(0) returns "one"

As advised in the Mockito documentation, doReturn must be used in that case:

  doReturn("one").when(spiedList).get(0)

Comment by tony.hillerson, Apr 14, 2009

here are the instructions for depending Mockito with Maven: http://code.google.com/p/mockito/wiki/MavenUsers


Sign in to add a comment
Hosted by Google Code