How to verify whether a function has been hit with pytest

Viewed 154

I have tried this:

def test_send_confirm_hit(monkeypatch):
    hit = False
    def called():
        global hit
        hit = True

    monkeypatch.setattr("web.email.send_confirm", called)

    # ... some event that will cause web.email.send_confirm to be hit

    assert hit  # verify send_confirm was hit

Which appears to work although I would rather not use a global variable. What is the best way to do this?

2 Answers

If you use a "proper" mock, it comes with an .assert_called() method:

import unittest.mock


def test_send_confirm_hit(monkeypatch):
    mock_send_confirm = unittest.mock.Mock()

    monkeypatch.setattr("web.email.send_confirm", mock_send_confirm)

    # ... some event that will cause web.email.send_confirm to be hit

    mock_send_confirm.assert_called()

You could use a Mock instead of the function:

from unittest.mock import MagicMock


def test_send_confirm_hit(monkeypatch):
    called = MagicMock()

    monkeypatch.setattr("web.email.send_confirm", called)

    # ... some event that will cause web.email.send_confirm to be hit

    assert called.call_count == 1  # verify send_confirm was hit

If you really need to perform some custom logic, like you would do with a function, you can add a side_effect to the mock:

def test_send_confirm_hit(monkeypatch):
    def side_effect():
        return 42

    called = MagicMock(side_effect=side_effect)
Related