I do not see the actual mock object created for the class instance which I am trying to mock in the following code.
class_to_be_mocked.py
class ClassToBeMocked():
def __init__(self):
pass
def method(self):
return "abc"
class_under_test.py
class ClassUnderTest():
def __init__(self):
self.api = ClassToBeMocked()
def method(self):
return self.api.method()
test.py
class TestClass(unittest.Testcase):
def setUp(self):
with patch('class_to_be_mocked.ClassToBeMocked') as mocked_class:
self.mocked_class_instance = mocked_class.return_value
def test_method(self):
instance = ClassUnderTest()
self.mocked_class_instance.method.return_value = "abc"
instance.method()
Related
I'm trying to mock a class in python with another class using unittest but the unittest.patch creates an instance from the mock class and replaces the original class with it. Here is the description
The Origin class is located in the file: src/libutil/util.py
class A:
def __init__(self) -> None:
self.a = self.g()
self.c = "parent"
def g(self):
return "HI from parent"
The mock class is located in the file tests/libraries/mocks/util.py
class B(A):
def __init__(self) -> None:
super().__init__()
def g(self):
return "Hi from child"
I'm mocking that using unittest as follows:
#pytest.fixture(scope="session", autouse=True)
def mock_util():
from tests.libraries.mocks.util import B
with mock.patch('libutil.util.A', new_callable=B, create=False) as util_mock:
yield util_mock
The problem is that the patch creates an instance from class B and replaces class A with it instead of replacing class A with class B itself. When I use a = libutil.util.A() that doesn't work and throws TypeError: 'B' object is not callable.
Can you help me in mocking class A with class B itself? Please note that the usage here is a simplified example.
Here is my code:
class class1():
def __init__(self):
pass
def method1(self):
pass
def independent_method(class1_instance, param2='method1'):
return class1_instance.param2()
c = class1()
independent_method(c)
I get this error:
'class1' object has no attribute 'param2'
How do I get around this problem? I've tried different variations.
Use __getattribute__ to fetch the method by its given name in param2:
class class1():
def __init__(self):
pass
def method1(self):
pass
def independent_method(class1_instance, param2='method1'):
return class1_instance.__getattribute__(param2)()
c = class1()
independent_method(c)
You can also use getattr... that's actually a better way to do so.
class class1():
def __init__(self):
pass
def method1(self):
pass
def independent_method(class1_instance, param2='method1'):
return getattr(class1_instance, param2)()
c = class1()
independent_method(c)
How can Python's unittest.mock module be used to mock a method that uses a member of the same class?
class NameHelper(object):
def __init__(self):
self.local_id = 0
def next_id(self):
self.local_id += 1
return str(self.local_id)
Note, I'm patch.start and patch.stop to do patching in the setUp method:
class TestSomeClient(unittest.TestCase):
def setUp(self):
patcher = patch('helpers.name_helper.NameHelper')
self.addCleanup(patcher.stop)
self.mock_name_helper = patcher.start()
# The actual mocked values
self.mock_name_helper.return_value.local_id = 0
self.mock_name_helper.return_value.next_id.return_value = 'mock-name'
Clearly, mock-name is not a sensible mock return value. The return value should use the local_id member of NameHelper.
I'm unsure why the question was down-voted with no comments. The answer is, IMO, not clear.
The Python documentation for patch.start and patch.stop, provides the following example for patching in setUp:
class MyTest(TestCase):
def setUp(self):
self.patcher1 = patch('package.module.Class1')
self.MockClass1 = self.patcher1.start()
def tearDown(self):
self.patcher1.stop()
MyTest('test_something').run()
However, when patching entire class, this is misleading. The following is more helpful:
class MockClass1():
pass
class MyTest(TestCase):
def setUp(self):
self.patcher1 = patch('package.module.Class1')
self.MockClass1 = self.patcher1.start()
self.MockClass1.return_value = MockClass1()
def tearDown(self):
self.patcher1.stop()
Note, the additional line:
self.MockClass1.return_value = MockClass1()
The return_value should be a new instance of the class MockClass1. Applied to my example:
class MockNameHelper(object):
def __init__(self):
self.local_id = 0
def next_id(self):
self.local_id += 1
return str(self.local_id)
class TestSomeClient(unittest.TestCase):
def setUp(self):
patcher = patch('helpers.name_helper.NameHelper')
self.addCleanup(patcher.stop)
self.MockNameHelper = patcher.start()
self.MockNameHelper.return_value = MockNameHelper()
I have the following situation.
class Class1():
def __init__(self, param1):
self.param = param1
def my_func_1(self):
return "Hello " + self.param1
class Class2():
def __init__(self):
self.instance_of_class_1 = Class1('Real')
def do_it(self):
return self.instance_of_class_1.my_func_1()
class Class3():
def __init__(self):
self.instace_of_class_2 = Class2()
def do_it(self):
return self.instace_of_class_2.do_it()
I have a test that initiates a Class3 object but I want to mock the new instance of Class1 inside the constructor of Class2. This is what i did so far:
def test_my_classes():
with patch('my.module.Class1') as class_1_mock:
class_1_mock.my_func_1.return_value = "Hello Fake"
class_3 = Class3()
assert class_3.do_it() == 'Hello Fake' #fails
I'm guessing because Class1 constructor takes params - its not a simple patch.
You are mocking Class1 correctly, but forgot to take into account it is called to produce an instance. The my_func_1 would be looked up on the call result (on the instance):
def test_my_classes():
with patch('my.module.Class1') as class_1_mock:
class_1_mock.return_value.my_func_1.return_value = "Hello Fake"
Mock doesn't care that you produced an instance or that my_func_1 is a bound method, only that you call Class1.
You can then make assertions if the class was called with the correct parameters, if you so desire:
class_1_mock.assert_called_once_with('Real')
Demo:
>>> from mock import patch
>>> class Class1():
... def __init__(self, param1):
... self.param = param1
... def my_func_1(self):
... return "Hello " + self.param1
...
>>> class Class2():
... def __init__(self):
... self.instance_of_class_1 = Class1('Real')
... def do_it(self):
... return self.instance_of_class_1.my_func_1()
...
>>> class Class3():
... def __init__(self):
... self.instace_of_class_2 = Class2()
... def do_it(self):
... return self.instace_of_class_2.do_it()
...
>>> with patch('__main__.Class1') as class_1_mock:
... class_1_mock.return_value.my_func_1.return_value = "Hello Fake"
... class_3 = Class3()
... print class_3.do_it() == 'Hello Fake'
...
True
>>> class_1_mock.mock_calls
[call('Real'), call().my_func_1()]
I included class_1_mock.mock_calls to show that call().my_func_1() is included; that's the Class1('Real') instance being used to provide the my_func_1() method call.
So I am trying to create a public method that can be called by class a so that it edits a data item in class b.
class aClass():
def __init__(self):
aVariable = 1
class aNotherClass():
def aMethod(self):
aFunction(5)
def aFunction(aNumber):
instance1.aVariable = aNumber
instance1 = aClass()
instance2 = aNotherClass()
instance2.aMethod
However, when I call instance1 in aFunction, python tells me it isn't defined. If I want to change aVariable in aClass, what should aFunction() say?
I think you may forget the self when you define a class method.
refer to: https://docs.python.org/2/tutorial/classes.html#class-objects
class aClass():
def __init__(self):
aVariable = 1
class aNotherClass():
def aMethod(self):
aFunction(5)
def aFunction(aNumber):
instance1.aVariable = aNumber
instance1 = aClass()
instance2 = aNotherClass()
instance2.aMethod()