The Walk-through

The 90% use case is that want to stub out a side effect. This is also known as (monkey-)patching. With mockito, it’s:

from mockito import when

# stub `os.path.exists`
when(os.path).exists('/foo').thenReturn(True)

os.path.exists('/foo')  # => True
os.path.exists('/bar')  # -> throws unexpected invocation

So in difference to traditional patching, in mockito you always specify concrete arguments (a call signature), and its outcome, usually a return value via thenReturn or a raised exception via thenRaise. That effectively turns function calls into constants for the time of the test.

There are of course reasons when you don’t want to overspecify specific tests. You _just_ want the desired stub answer. Here we go:

when(os.path).exists(...).thenReturn(True)

# now, obviously, you get the same answer, regardless of the arguments
os.path.exists('FooBar')  # => True
os.path.exists('BarFoo')  # => True

You can combine both stubs. E.g. nothing exists, except one file:

when(os.path).exists(...).thenReturn(False)
when(os.path).exists('.flake8').thenReturn(True)

And because it’s a similar pattern, we can introduce spy2() here. Spies call through the original implementation of a given function. E.g. everything is as it is, except ‘.flake8’ is just not there:

from mockito import spy2
spy2(os.path.exists)
when(os.path).exists('.flake8').thenReturn(False)

Another way to write the same thing is:

when(os.path).exists(...).thenCallOriginalImplementation()
when(os.path).exists('.flake8').thenReturn(False)

And actually spy2 uses thenCallOriginalImplementation under the hood. Why spying at all: either you want the implementation almost intact as above or you need the implementation to stay intact but want to verify its usage. E.g.:

spy2(os.path.exists)
# now do some stuff
do_stuff()
# then verify the we asked for the cache exactly once
verify(os.path, times=1).exists("cache/.foo")

When patching, you MUST not forget to unstub() of course! You can do this explicitly

from mockito import unstub
unstub()  # restore os.path module

Usually you do this unconditionally in your teardown function. If you’re using pytest, you could define a fixture instead

# conftest.py
import pytest

@pytest.fixture
def unstub():
    from mockito import unstub
    yield
    unstub()

# my_test.py
import pytest
pytestmark = pytest.mark.usefixtures("unstub")

But very often you just use context managers (aka with), and mockito will unstub on ‘exit’ automatically:

# E.g. test that `exists` gets never called
with expect(os.path, times=0).exists('.flake8'):
    # within the block `os.path.exists` is patched
    cached_dir_lookup('.flake8')
# at the end of the block `os.path` gets unpatched

# Which is btw roughly the same as doing
with when(os.path).exists('.flake8'):
    cached_dir_lookup('.flake8')
    verify(os.path, times=0).exists(...)

Now let’s mix global module patching with mocks. We want to test the following function using the fab requests library:

import requests

def get_text(url):
    res = requests.get(url)
    if 200 <= res.status_code < 300:
        return res.text
    return None

How, dare, we did not inject our dependencies! Obviously we can get over that by patching at the module level like before:

when(requests).get('https://example.com/api').thenReturn(...)

But what should we return? We know it’s a requests.Response object, (Actually I know this bc I typed this in the ipython REPL first.) But how to construct such a Response, its __init__ doesn’t even take any arguments?

Should we actually use a ‘real’ response object? No, we fake it using mock().

# setup
response = mock({
    'status_code': 200,
    'text': 'Ok'
}, spec=requests.Response)
when(requests).get('https://example.com/api').thenReturn(response)

# run
assert get_text('https://example.com/api') == 'Ok'

# done!

Say you want to mock the class Dog:

class Dog(object):
    def bark(self):
        return 'Wuff'


# either mock the class
when(Dog).bark().thenReturn('Miau!')
# now all instances have a different behavior
rex = Dog()
assert rex.bark() == 'Miau!'

# or mock a concrete instance
when(rex).bark().thenReturn('Grrrr')
assert rex.bark() == 'Grrrr'
# a different dog will still 'Miau!'
assert Dog().bark() == 'Miau!'

# be sure to call unstub() once in while
unstub()

Sure, you can verify your interactions:

from mockito import verify
# once again
rex = Dog()
when(rex).bark().thenReturn('Grrrr')

rex.bark()
rex.bark()

# `times` defaults to 1
verify(rex, times=2).bark()

In general mockito is very picky:

# this will fail because `Dog` has no method named `waggle`
when(rex).waggle().thenReturn('Nope')
# this will fail because `bark` does not take any arguments
when(rex).bark('Grrr').thenReturn('Nope')


# given this function
def bark(sound, post='!'):
    return sound + post

from mockito import kwargs
when(main).bark('Grrr', **kwargs).thenReturn('Nope')

# now this one will fail
bark('Grrr')  # because there are no keyword arguments used
# this one will fail because `then` does not match the function signature
bark('Grrr', then='!!')
# this one will go
bark('Grrr', post='?')

# there is also an args matcher
def add_tasks(*tasks, verbose=False):
    pass

from mockito import args
# If you omit the `thenReturn` it will just return `None`
when(main).add_tasks(*args)

add_tasks('task1', 'task2')  # will go
add_tasks()  # will fail
add_tasks('task1', verbose=True)  # will fail too

# On Python 3 you can also use `...`
when(main).add_tasks(...)
# when(main).add_tasks(Ellipsis) on Python 2

add_tasks('task1')  # will go
add_tasks(verbose=True)  # will go
add_tasks('task1', verbose=True)  # will go
add_tasks()  # will go

To start with an empty stub use mock():

from mockito import mock

obj = mock()

# pass it around, eventually it will be used
obj.say('Hi')

# back in the tests, verify the interactions
verify(obj).say('Hi')

# by default all invoked methods take any arguments and return None
# you can configure your expected method calls with the usual `when`
when(obj).say('Hi').thenReturn('Ho')

# There is also a shortcut to set some attributes
obj = mock({
    'hi': 'ho'
})

assert obj.hi == 'ho'

# This would work for methods as well; in this case
obj = mock({
    'say': lambda _: 'Ho'
})

# But you don't have any argument and signature matching
assert obj.say('Anything') == 'Ho'

# At least you can verify your calls
verify(obj).say(...)

# Btw, you can make screaming strict mocks::
obj = mock(strict=True)  # every unconfigured, unexpected call will raise

You can use an empty stub specced against a concrete class:

# Given the above `Dog`
rex = mock(Dog)

# Now you can stub out any known method on `Dog` but other will throw
when(rex).bark().thenReturn('Miau')
# this one will fail
when(rex).waggle()

# These mocks are in general very strict, so even this will fail
rex.health  # unconfigured attribute

# Of course you can just set it in a setup routine
rex.health = 121

# Or again preconfigure
rex = mock({'health': 121}, spec=Dog)

# preconfigure stubbed method
rex = mock({'bark': lambda sound: 'Miau'}, spec=Dog)

# as you specced the mock, you get at least function signature matching
# `bark` does not take any arguments so
rex.bark('sound')  # will throw TypeError

# Btw, you can make loose specced mocks::
rex = mock(Dog, strict=False)