Python unittest.mock (Survey)
A mock is a fake object that records every call made on it. A test uses a mock for code that talks to the outside world.
A Mock records its calls
called tells you the method ran. call_args shows the last call.
from unittest.mock import Mock
sender = Mock()
sender.send("Hello!")
print(sender.send.called)
print(sender.send.call_count)
print(sender.send.call_args)Set a return value
Tell the fake what to hand back, then use it like the real thing.
from unittest.mock import Mock
api = Mock()
api.get_price.return_value = 42
print(api.get_price("apple"))
print(api.get_price.called)patch swaps a name for a while
Inside the block the name is fake. After the block it is real again.
from unittest.mock import patch
def get_name():
return "real"
with patch("__main__.get_name", return_value="fake"):
print(get_name())
print(get_name())Check that nothing was called
This assert fails if the fake was used at all.
fake_sender.assert_not_called()Example
import unittest
from unittest.mock import patch
def send_email(address, message):
print("Real sending to", address)
def notify_user(address, message):
if not address:
return False
send_email(address, message)
return True
class TestNotify(unittest.TestCase):
def test_notify_calls_sender_once(self):
with patch("test_notifier.send_email") as fake:
result = notify_user("ana@example.com", "Hi!")
self.assertTrue(result)
fake.assert_called_once_with("ana@example.com", "Hi!")
def test_empty_address_sends_nothing(self):
with patch("test_notifier.send_email") as fake:
result = notify_user("", "Hi!")
self.assertFalse(result)
fake.assert_not_called()
def test_message_goes_through_unchanged(self):
with patch("test_notifier.send_email") as fake:
notify_user("bo@example.com", "Meeting moved")
fake.assert_called_once_with("bo@example.com", "Meeting moved")
if __name__ == "__main__":
unittest.main()Key points
- Mock: a fake object that records every call made on it.
- A mock accepts any call and returns another mock, unless you set a return value.
- Use patch to swap one name for a fake during a single test.
- Use assert_called_once_with to check the exact call your code made.
- Mock what you do not own, like a sender, a clock, or a web service.
- Mock sparingly.
- A test full of mocks tests the mocks, not your code.
- patch restores the real object when the with block ends.
In this example, the whole program lives in one file, test_notifier.py. The function notify_user calls the module-level send_email. Each test patches that name, so no real mail can leave. The patch target names the module, test_notifier, and then the function. The first test checks the exact address and message of the single call. The second test checks that an empty address sends nothing at all. Run the file with python3 -m unittest test_notifier. The Ran line also reports a varying time in seconds. OK means all three tests passed.
Note
Nothing stays swapped after the test.
Try it Yourself
Edit the code, then press Run.
Running is simulated · Python Playground
Exercise
When is a mock the right tool in a test?