chm
chm

Reputation: 485

Python mockito: mock a single function

I need to mock a single function (not a class member and not a part of an imported module) in mockito. I read that mockito mocks are callable so I can use __call__() function but unfortunately it does not work for me. There is an old question about it asked 3 years ago and I suppose that maybe something has changes since that time (so please do not resolve this question as a duplicate of that old thread).

Here is the example code (taken from that old thread):

import os
import unittest
from mockito import when, verify

def interesting_function():
    os.system('mkdir some_dir')
    another_function()

def another_function():
    print('Done')

class InterestingFunctionTests(unittest.TestCase):
    def test_interesting_function(self):
         when(another_function).__call__().thenReturn()
         interesting_function()
         verify(another_function).__call__()

It was supposed to work I'm getting the following error:

mockito.verification.VerificationError:
Wanted but not invoked:

    __call__()

Instead got:

    Nothing

How can I mock and verify a single function in mockito?

I appreciate any help.

Upvotes: 1

Views: 1106

Answers (1)

herr.kaste
herr.kaste

Reputation: 558

The answer to the old question is just wrong. And it was wrong at that time as well.

You read that "mocks are callable" and that just means

m = mock()
m()  # => None

mocks are pre-configured to be callable. That's a special case because otherwise plain mocks are totally dumb. (The user has to configure them.)

But here you don't even want mocks, you want to patch (or: monkey-patch) functions. Actually, you don't patch functions (what does that mean) you monkey patch the module the fucntion lives in. The module is also an object.

Consider:

def interesting():
    also()

If you call interesting(), python stumbles upon the name also and looks that up, first in the local function scope, and then in the outer, global, module scope. That means, if you replace <module>.also you get the desired effect in not calling the "real" function also but a fake one.

So the general form

# the test.py
import some_module as module_under_test

def test_1():
    when(module_under_test).also()
    ...
    unstub()  # t.i. restore/undo the patching

Having a test file and an implementation file makes this easy because patching the test module while you're in the test module -- that is your example: interesting_function lives in the test file -- you usually don't know what to patch, but it is actually sys.modules[__name__] that is your current module object.

Upvotes: 1

Related Questions