I am trying to mock a class and its method that is used by another class.
My file structure is:
[1] my_animal.py contains Myclass and method: do_bite()
my_animal.py
class Myclass():
def do_bite(self):
return 1
[2] my_module.py contains jobMain("") which is using the method from my_animal.py
my_module.py
import sys
from my_animal import Myclass
def jobMain(directoryPath):
result = Myclass()
if result.do_bite() is None:
sys.exit(1) # stop here
[3] my_test.py contains the unittest to test jobMain in my_module.py
my_test.py
from my_animal import Myclass
# Try to mock Myclass
#pytest.fixture
def mock_Myclass(monkeypatch):
""" Mock myclass """
monkeypatch.setattr(my_module, "Myclass", MagicMock())
# I tried below code to mock dobite() method, but it was unsuccessfully
# Mock Myclass.dobite to None"""
#pytest.fixture
def mock_dobite(monkeypatch):
def mock_return(*args, **kwargs):
with patch('my_animal',dobite) as p:
instance = p.return_value
instance.dobite = Mock(return_value = None)
monkeypatch.setattr(my_module.Myclass, "do_bite", mock_return )
# My unittest to test dobite() method
def test_dobite(mock_Myclass, mock_dobite):
with pytest.raises(SystemExit) as s_exit:
jobMain("")
assert s_exit.type == SystemExit
assert s_exit.value.code == 1
My question is: How could I mock the return value of the method do_bite() to None or any other expected value?
Your fixture is overly complicated, here is what you can use:
import pytest
from unittest import mock
#pytest.fixture
def mock_dobite():
with mock.patch('my_module.Myclass') as mocked_animal:
mocked_animal.return_value.do_bite.return_value = None
yield
You patch the class as it is imported (see where to patch). Because Myclass is imported like this:
from my_animal import Myclass
you have a local reference to the module, which you have to patch.
mocked_animal is the mocked class. To get the instance of the class, you have to use mocked_animal.return_value. By adding do_bite.return_value, you now can set the return value of the method do_bite.
Now your test will work like this (note that you need only one fixture parameter):
def test_dobite(mock_dobite):
with pytest.raises(SystemExit) as s_exit:
jobMain("")
assert s_exit.type == SystemExit
assert s_exit.value.code == 1
Is there a clean way to patch an object so that you get the assert_call* helpers in your test case, without actually removing the action?
For example, how can I modify the #patch line to get the following test passing:
from unittest import TestCase
from mock import patch
class Potato(object):
def foo(self, n):
return self.bar(n)
def bar(self, n):
return n + 2
class PotatoTest(TestCase):
#patch.object(Potato, 'foo')
def test_something(self, mock):
spud = Potato()
forty_two = spud.foo(n=40)
mock.assert_called_once_with(n=40)
self.assertEqual(forty_two, 42)
I could probably hack this together using side_effect, but I was hoping there would be a nicer way which works the same way on all of functions, classmethods, staticmethods, unbound methods, etc.
Similar solution with yours, but using wraps:
def test_something(self):
spud = Potato()
with patch.object(Potato, 'foo', wraps=spud.foo) as mock:
forty_two = spud.foo(n=40)
mock.assert_called_once_with(n=40)
self.assertEqual(forty_two, 42)
According to the documentation:
wraps: Item for the mock object to wrap. If wraps is not None then
calling the Mock will pass the call through to the wrapped object
(returning the real result). Attribute access on the mock will return
a Mock object that wraps the corresponding attribute of the wrapped
object (so attempting to access an attribute that doesn’t exist will
raise an AttributeError).
class Potato(object):
def spam(self, n):
return self.foo(n=n)
def foo(self, n):
return self.bar(n)
def bar(self, n):
return n + 2
class PotatoTest(TestCase):
def test_something(self):
spud = Potato()
with patch.object(Potato, 'foo', wraps=spud.foo) as mock:
forty_two = spud.spam(n=40)
mock.assert_called_once_with(n=40)
self.assertEqual(forty_two, 42)
This answer address the additional requirement mentioned in the bounty from user Quuxplusone:
The important thing for my use-case is that it work with #patch.mock, i.e. that it not require me to insert any code in between my constructing of the instance of Potato (spud in this example) and my calling of spud.foo. I need spud to be created with a mocked-out foo method from the get-go, because I do not control the place where spud is created.
The use case described above could be achieved without too much trouble by using a decorator:
import unittest
import unittest.mock # Python 3
def spy_decorator(method_to_decorate):
mock = unittest.mock.MagicMock()
def wrapper(self, *args, **kwargs):
mock(*args, **kwargs)
return method_to_decorate(self, *args, **kwargs)
wrapper.mock = mock
return wrapper
def spam(n=42):
spud = Potato()
return spud.foo(n=n)
class Potato(object):
def foo(self, n):
return self.bar(n)
def bar(self, n):
return n + 2
class PotatoTest(unittest.TestCase):
def test_something(self):
foo = spy_decorator(Potato.foo)
with unittest.mock.patch.object(Potato, 'foo', foo):
forty_two = spam(n=40)
foo.mock.assert_called_once_with(n=40)
self.assertEqual(forty_two, 42)
if __name__ == '__main__':
unittest.main()
If the method replaced accepts mutable arguments which are modified under test, you might wish to initialize a CopyingMock* in place of the MagicMock inside the spy_decorator.
*It's a recipe taken from the docs which I've published on PyPI as copyingmock lib
For those who don't mind using side_effect, here's a solution with a few pros:
Uses decorator syntax
Patches an unbound method, which I find more versatile
Requires inclusion of the instance in the assertion
class PotatoTest(TestCase):
#patch.object(Potato, 'foo', side_effect=Potato.foo, autospec=True)
def test_something(self, mock):
spud = Potato()
forty_two = spud.foo(n=40)
mock.assert_called_once_with(spud, n=40)
self.assertEqual(forty_two, 42)
You are describing the same question than Python mock: wrap instance method. My solution in https://stackoverflow.com/a/72446339/9230828 can be applied as following: Put wrap_object somewhere, e.g. into wrap_object.py:
# Copyright (C) 2022, Benjamin Drung <bdrung#posteo.de>
#
# Permission to use, copy, modify, and/or distribute this software for any
# purpose with or without fee is hereby granted, provided that the above
# copyright notice and this permission notice appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
import contextlib
import typing
import unittest.mock
#contextlib.contextmanager
def wrap_object(
target: object, attribute: str
) -> typing.Generator[unittest.mock.MagicMock, None, None]:
"""Wrap the named member on an object with a mock object.
wrap_object() can be used as a context manager. Inside the
body of the with statement, the attribute of the target is
wrapped with a :class:`unittest.mock.MagicMock` object. When
the with statement exits the patch is undone.
The instance argument 'self' of the wrapped attribute is
intentionally not logged in the MagicMock call. Therefore
wrap_object() can be used to check all calls to the object,
but not differentiate between different instances.
"""
mock = unittest.mock.MagicMock()
real_attribute = getattr(target, attribute)
def mocked_attribute(self, *args, **kwargs):
mock.__call__(*args, **kwargs)
return real_attribute(self, *args, **kwargs)
with unittest.mock.patch.object(target, attribute, mocked_attribute):
yield mock
Then you can write following unit test:
from unittest import TestCase
from wrap_object import wrap_object
class Potato:
def foo(self, n):
return self.bar(n)
def bar(self, n):
return n + 2
class PotatoTest(TestCase):
def test_something(self):
with wrap_object(Potato, 'foo') as mock:
spud = Potato()
forty_two = spud.foo(n=40)
mock.assert_called_once_with(n=40)
self.assertEqual(forty_two, 42)
I did it with a bit another way because IMO mocking is preferable over patching
from unittest.mock import create_autospec
mocked_method = create_autospec(
spec=my_method,
spec_set=True,
# Will implement a real behavior rather than return a Mock instance
side_effect=*a, **kw: my_method.do_something(*a, **kw))
mocked_object.do_something()
mocked_object.assert_called_once()
I've read a lot of information online about mocking entire classes. However, I have a class with multiple methods; for example:
class A():
def methoda(param1, param2):
do things
return thing
def methodb(param3):
do things (including something calling methoda)
How can I mock out methoda in a testing file to return a desired value so that I can test methodb? I don't want to mock out the entire class.
What I've tried doing:
from mock import patch, mock, MagicMock
from sourceA.models import ClassName
from django.test import TestCase
class ClassTest(TestCase):
#patch('sourceA.models.ClassName.methodA')
def test_method(self, mock_method_return):
mock_method_return.return_value = 10
instance = ClassName()
instance.methodB #METHOD B CALLS METHOD A; I want method A to return 10
print "OUTPUT", instance.FIELDA #Debug Tool - Field A is modified by Method B, based on the return value of method A
assert instance.FIELDA == 10
I have also tried this:
class ClassTest(TestCase):
#patch('sourceA.models.ClassName.methodA', return_value=10)
def test_method(self, mock_method_return):
instance = Mock(spec=ClassName())
instance.methodB #METHOD B CALLS METHOD A; I want method A to return 10
------ OR instance methodB = MagicMock(return_value=10) and then instance.MethodB
print "OUTPUT", instance.FIELDA #Debug Tool - Field A is modified by Method B, based on the return value of method A
self.assertEqual(instance.FIELDA, 10)
I'm not sure what else I should try/what I am doing wrong.
I am interested in patching a method which is called by another method in one file. Example - original.py file contains -
def A():
a = 10
b = 5
return a*b;
def B():
c = A()
return c* 10
I want to write unit test for this file , say call it test.py
import mock
import unittest
class TestOriginal(unitest.TestCase):
def test_Original_method(self):
with patch(''):
How can I use patch and mock modules to test original.py. I want A() to always return MagicMock() object instead of an integer.
You simply patch out the A global in the module under test. I'd use the #patch decorator syntax here:
import mock
import unittest
import module_under_test
class TestOriginal(unitest.TestCase):
#patch('module_under_test.A')
def test_Original_method(self, mocked_A):
mocked_A.return_value = 42
result = module_under_test.B()
mocked_A.assert_called_with()
self.assertEqual(result, 420)
This passes in the MagicMock mock object for A() as an extra argument to the test method.
Note that we explicitly named the module here. You could also use patch.object(), just naming the attribute on the module (which are your module globals):
class TestOriginal(unitest.TestCase):
#patch.object(module_under_test, 'A')
def test_Original_method(self, mocked_A):
mocked_A.return_value = 42
result = module_under_test.B()
mocked_A.assert_called_with()
self.assertEqual(result, 420)
You can still use a with statement too, of course:
class TestOriginal(unitest.TestCase):
def test_Original_method(self):
with patch('module_under_test.A') as mocked_A:
mocked_A.return_value = 42
result = module_under_test.B()
mocked_A.assert_called_with()
self.assertEqual(result, 420)
OK,
I know this is mentioned in the manual, and probably has to do with side_effect and/or return_value, but a simple, direct example will help me immensely.
I have:
class ClassToPatch():
def __init__(self, *args):
_do_some_init_stuff()
def some_func():
_do_stuff()
class UUT():
def __init__(self, *args)
resource_1 = ClassToPatch()
resource_2 = ClassToPatch()
Now, I want to unit test the UUT class, and mock the ClassToPatch. Knowing the UUT class will instantiate exactly two ClassToPatch objects, I want the Mock framework to return a new Mock object for each instantiation, so I can later assert calls on each separately.
How do I achieve this using the #patch decorator in a test case? Namely, how to fix the following code sample?
class TestCase1(unittest.TestCase):
#patch('classToPatch.ClassToPatch',autospec=True)
def test_1(self,mock1,mock2):
_assert_stuff()
Here's a quick'n'dirty example to get you going:
import mock
import unittest
class ClassToPatch():
def __init__(self, *args):
pass
def some_func(self):
return id(self)
class UUT():
def __init__(self, *args):
resource_1 = ClassToPatch()
resource_2 = ClassToPatch()
self.test_property = (resource_1.some_func(), resource_2.some_func())
class TestCase1(unittest.TestCase):
#mock.patch('__main__.ClassToPatch', autospec = True)
def test_1(self, mock1):
ctpMocks = [mock.Mock(), mock.Mock()]
ctpMocks[0].some_func.return_value = "funky"
ctpMocks[1].some_func.return_value = "monkey"
mock1.side_effect = ctpMocks
u = UUT()
self.assertEqual(u.test_property, ("funky", "monkey"))
if __name__ == '__main__':
unittest.main()
I've added test_property to UUT so that the unit test does something useful. Now, without the mock test_property should be a tuple containing the ids of the two ClassToPatch instances. But with the mock it should be the tuple: ("funky", "monkey").
I've used the side_effect property of the mock object so that a different instance of ClassToPatch is returned on each call in the UUT initialiser.
Hope this helps.
Edit: Oh, by the way, when I run the unit test I get:
.
----------------------------------------------------------------------
Ran 1 test in 0.004s
OK
Here is another version which is more generic to handle any number of instances created:
class TestUUT:
def test_init(self, mocker):
class MockedClassToPatchMeta(type):
static_instance = mocker.MagicMock(spec=ClassToPatch)
def __getattr__(cls, key):
return MockedClassToPatchMeta.static_instance.__getattr__(key)
class MockedClassToPatch(metaclass=MockedClassToPatchMeta):
original_cls = ClassToPatch
instances = []
def __new__(cls, *args, **kwargs):
MockedClassToPatch.instances.append(
mocker.MagicMock(spec=MockedClassToPatch.original_cls))
MockedClassToPatch.instances[-1].__class__ = MockedClassToPatch
return MockedClassToPatch.instances[-1]
mocker.patch(__name__ + '.ClassToPatch', new=MockedClassToPatch)
UUT()
# since your original code created two instances
assert 2 == len(MockedClassToPatch.instances)
If you need more thorough validation for each instance you can access MockedClassToPatch.instances[0] or MockedClassToPatch.instances[1].
I've also created a helper library to generate the meta class boilerplate for me. To generate the needed code for your example I wrote:
print(PytestMocker(mocked=ClassToPatch, name=__name__).mock_classes().mock_classes_static().generate())