Skip to content

Instantly share code, notes, and snippets.

@mmasashi
Last active August 22, 2023 12:33
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mmasashi/d45d2fc5f32fba9ae2b91506976099a8 to your computer and use it in GitHub Desktop.
Save mmasashi/d45d2fc5f32fba9ae2b91506976099a8 to your computer and use it in GitHub Desktop.
Behavior of mock, patch, pytest mocker, examples
import contextlib
import pytest
from unittest.mock import patch
class A(object):
def say(self, msg):
return f'A say {msg!r}.'
@contextlib.contextmanager
def start(self, msg):
print(f'A start --- {msg!r}')
yield f'yield from A - {msg!r}'
print(f'B end --- {msg!r}')
def test_say():
assert A().say('hello') == "A say 'hello'."
def test_patched_say1(mocker):
with patch.object(A, 'say', return_value='hogehoge') as mock_say:
a = A()
assert a.say('hello') == "hogehoge"
mock_say.assert_called_once_with('hello')
def test_patched_say2(mocker):
def ret_fugafuga(*args):
return 'fugafuga'
with patch.object(A, 'say', wraps=ret_fugafuga) as mock:
print(mock)
assert A().say('hello') == "fugafuga"
mock.assert_called_once_with('hello')
def test_patched_say3(mocker):
a_say = A.say
def wrapped_say(self, *args):
return f'Wrap say - {a_say(self, *args)}'
mocker.patch.object(A, 'say', new=wrapped_say)
assert A().say('hello') == "Wrap say - A say 'hello'."
def test_patched_say4():
with patch.object(A, 'say') as mock:
mock.return_value = 'hogehoge'
assert A().say('hello') == "hogehoge"
mock.assert_called_once_with('hello')
def test_patched_say5(mocker):
# Using mocker.patch as context manager is not supported
# https://pypi.org/project/pytest-mock/
with mocker.patch.object(A, 'say') as mock:
mock.return_value = 'hogehoge'
with pytest.raises(AssertionError):
assert A().say('hello') == "hogehoge" # Doesn't work
with pytest.raises(AssertionError):
mock.assert_called_once_with('hello') # Doesn't work
def test_start():
with A().start('hello') as msg:
assert msg == "yield from A - 'hello'"
def test_patch_start1():
with patch.object(A, 'start') as mock_start:
mock_start.return_value.__enter__.return_value = 'yield from mock'
with A().start('hello') as msg:
assert msg == 'yield from mock'
def test_patch_start2():
a_start = A.start
@contextlib.contextmanager
def wrap_start(self, msg):
print(f'wrap_start start - {msg}')
with a_start(self, msg) as orig_msg:
yield f'yield from wrap_start - {orig_msg!r}'
print(f'wrap_start end - {msg}')
with patch.object(A, 'start', wrap_start) as mock_start:
with A().start('hello') as msg:
assert msg == "yield from wrap_start - \"yield from A - 'hello'\""
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment