Reputation: 2663
I have a file copy_x_to_y.py which goes like this:
from abcd import F
def function_to_be_tested():
F()
in abcd.py file, i have something like this:
from xyz import XY
class F():
def __init__(self, arg1):
self.xy = XY(arg1)
I want to mock init of XY in my test case. I have tried mocking F's init with:
def mock_func(*args, **kwargs):
pass
@patch('path/to/copy_x_to_y.F.__init__', mock_func)
def test():
assert function_to_be_tested() is None
but it always happens to call XY's init, resulting in error as its initialization calls to connect with S3 with arg1. How to test this kind of structure?
Upvotes: 2
Views: 4904
Reputation: 91
What is the reason for wanting to mock __init__
of XY
? Do you want it to return a specific object of XY, do you want to check if XY.__init__
was called with specific arguments or something else?
A possible solution to your problem would be to mock the entire class, but have it return a "normal" object. Here's an example:
>>> from unittest.mock import patch
>>> class MyClass:
... def __init__(self, val):
... self._val = val
... def foo(self):
... print(self._val)
...
>>> a = MyClass(1)
>>> a.foo()
1
>>> patcher = patch('__main__.MyClass', return_value=a)
>>> mock_class = patcher.start()
>>> b = MyClass(2) # This will return a.
>>> b.foo()
1
>>> mock_class.call_args_list
[call(2)]
>>> patcher.stop()
Which in your case would be:
from xyz import XY
from path/to/copy_x_to_y import function_to_be_tested
def test():
arg1 = ...
a = XY(arg1) # Has to be called before the patch to get a "normal" object.
with patch('xyz.XY', return_value=a) as mock_xy:
# Run funcion to be tested here and check results.
function_to_be_tested()
assert ...
__init__
directly though, if that's really what you need to do.>>> def my_init(self, *args, **kwargs):
... self._val = 1
>>> patcher = patch.object(MyClass, '__init__', my_init)
>>> mock_init = patcher.start()
>>> a = MyClass(2)
>>> a.foo()
1
@patch('path/to/SomeClass', ...)
def test(mock_class):
...
Upvotes: 6