Last active
August 22, 2023 12:33
-
-
Save mmasashi/d45d2fc5f32fba9ae2b91506976099a8 to your computer and use it in GitHub Desktop.
Behavior of mock, patch, pytest mocker, examples
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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