How to mock nested method call in Python - python

I am quite new to Python. I have OpenshiftApiController class and a test class TestOpenshiftApiController. I am using python unittest library for Testing.
(1) In setUp() method of test class I am creating one object of OpenshiftApiController class and that class have below line in constructor. I want to mock DynamicClient(base_kube_client) which is present in __init__() of the actual class.
self.dynamic_client = DynamicClient(base_kube_client)
(2) Also in test_create_object() of Test class, I am calling create_object() of OpenshiftApiController class and there I want to mock nested method resource_client.create(**create_args) which is present in create_object() of actual class.
return_obj = resource_client.create(**create_args)
Actual Class to be tested:
class OpenshiftApiController:
def __init__(self, base_kube_client, default_namespace=DEFAULT_NAMESPACE):
self.base_kube_client = base_kube_client
self.dynamic_client = DynamicClient(base_kube_client)
self.default_namespace = default_namespace
def create_object(self, object_config, default_namespace=None, driver_request_id=None):
resource_client = self.__get_resource_client()
create_args = self.__build_create_arguments(resource_client, object_config, default_namespace)
return_obj = resource_client.create(**create_args)
return return_obj
Test Class:
class TestOpenshiftApiController(unittest.TestCase):
def setUp(self):
self.base_kube_client = client.ApiClient()
self.api_ctl = OpenshiftApiController(self.base_kube_client, default_namespace='default')
def test_create_object(self):
object_config = ObjectConfiguration()
self.api_ctl.create_object(object_config)
How to mock those 2 things? Any help is highly appreciable.

Related

inject method to class with decorator(or some other way)

I have classes defined for ORM. I want override some method of it but because there is many classes of them i prefer somehow dynamically inject it.
class Example(model.model):
name = SomeField()
lastname = SomeField()
#framework.decorator
def method_that_shows_fields(self):
res = super(self).method_that_shows_fields()
need_hide=['name']
for i in need_hide:
res[i]=False
return False
I thought I could write decorator where I pass what I want
def hide_decorator(*args):
def inner(cls):
def inner_fun(inst):
return hid_func(inst)
cls.method_that_shows_field= inner_fun
return cls
...
#hide_decorator("name,lastname")
class Example:
...
There is some very bad example code but u got the details.
It is not working because of super() call needed in function and parent changes during that time.
Python gurus: any idea how would you do that?

How to patch an object's attributes with `side_effect`

So I have a file some_class.py with:
class SomeReader:
def read_path(self, url):
return "read_path"
class SomeClass:
def __init__(self, url):
self.reader = SomeReader(url)
print(self.reader.read_path(""))
And a test file some_class_test.py:
from some_class import SomeClass, SomeReader
#patch("some_class.SomeReader")
def test_some_class(mock_some_reader):
def mock_read_path(url):
return "mock_read_path"
mock_some_reader.read_path.side_effect = mock_read_path
SomeClass("")
I'm expecting that when I run this test, it will print mock_read_path but instead it prints <MagicMock name='SomeReader().read_path()' id='140701381288480'>. How do I fix this? I want to mock both the class initialization of SomeReader, hence I use #patch("some_class.SomeReader"). But I also want to mock the read_path function of SomeReader, hence I have mock_some_reader.read_path.side_effect = mock_read_path but that doesn't seem to work.
What you're doing is making a mock of the class itself, not the instances of the classes. The mock replaces call to instantiate SomeReader(url) (basically replacing the __init__ method of the class).
What you want to do is then mock the return value of the fake instance being created by SomeReader(url)
#patch("some_class.SomeReader")
def test_some_class(mock_some_reader):
def mock_read_path(url):
return "mock_read_path"
mock_some_reader.return_value.read_path.side_effect = mock_read_path
SomeClass("")

python #patch custom patched object not updating

I want to patch a function(func_to_be_mocked ) returning class object (ReturnValue) with my own mocked version (ReturnValueMock). The function I want to test(func_to_be_tested) is setting some values on the object. But my mocked object is not getting updated and showing the deafult values. (i.e. assert statement in test is failing). What am I missing?
to_test.py
class ReturnValue():
def __init__(self):
self.a = ""
class ToTest():
def func_to_be_mocked(self):
return ReturnValue()
def func_to_be_tested(self):
ret_val = self.func_to_be_mocked()
ret_val.a = "set"
test.py
from mock import patch
import unittest
from .to_test import ToTest
class ReturnValueMock():
def __init__(self):
self.a = ""
class Tests(unittest.TestCase):
def setUp(self):
self.ret_val = ReturnValueMock()
#patch("to_test.ToTest.func_to_be_mocked")
def test(self, mocked_func):
mocked_func.return_val = self.ret_val
ToTest().func_to_be_tested()
assert self.ret_val == "set"
Thing tried so far
Added print statements to verify that the object in function under test is same as the one I am providing as mock (Object hash code code are same)

Defining a class inside a function to interrupt decorator execution

I'm trying to configure a decorator at run time. This is somewhat related to my earlier question: How to configure a decorator in Python
The motivation for this is that I'm trying to use the Thespian troupe code "as-is".
Is it legal to have this code here, where I've defined the class (and therefore called the decorator) inside a class method? Again, the reason for this is that I could feed the max_count argument prior to the decorator being call.
The module is calculator.calculator (yes, bad choice perhaps)
class Scheduler:
def __init__(self):
self.actor_system = None
def start(self):
self.actor_system = ActorSystem('multiprocTCPBase')
def stop(self):
self.actor_system.shutdown()
def launch(self, count, func_and_data, status_cb):
class CalcPayload:
def __init__(self, func_and_data, status_cb):
self.func_and_data = func_and_data
self.status_cb = status_cb
#troupe(max_count=count)
class Execute(ActorTypeDispatcher):
def receiveMsg_CalcPayload(self, msg, sender):
func = msg.func_and_data['func']
data = msg.func_and_data['data']
status_cb = msg.status_cb
self.send(sender, func(data, status_cb))
exec_actor = self.actor_system.createActor(Execute)
for index in range(len(func_and_data)):
calc_config = CalcPayload(func_and_data[index], status_cb)
self.actor_system.tell(exec_actor, calc_config)
for index in range(len(func_and_data)):
result = self.actor_system.listen(timeout)
self.actor_system.tell(exec_actor, ActorExitRequest())
For various reasons, I can't apply the decorator to the class when I use it. There is a brief discussion on this in the question I referenced.
While not invalid, it is generally inadvisable to define a class as a local variable inside a function, as it would make access to the class difficult outside the function.
Instead, you can define the classes outside the function, and apply the decorator function to the class when it's actually needed by calling the decorator function with the class object:
class CalcPayload:
def __init__(self, func_and_data, status_cb):
self.func_and_data = func_and_data
self.status_cb = status_cb
class Execute(ActorTypeDispatcher):
def receiveMsg_CalcPayload(self, msg, sender):
func = msg.func_and_data['func']
data = msg.func_and_data['data']
status_cb = msg.status_cb
self.send(sender, func(data, status_cb))
class Scheduler:
def __init__(self):
self.actor_system = None
def start(self):
self.actor_system = ActorSystem('multiprocTCPBase')
def stop(self):
self.actor_system.shutdown()
def launch(self, count, func_and_data, status_cb):
exec_actor = self.actor_system.createActor(troupe(max_count=count)(Execute))
for index in range(len(func_and_data)):
calc_config = CalcPayload(func_and_data[index], status_cb)
self.actor_system.tell(exec_actor, calc_config)
for index in range(len(func_and_data)):
result = self.actor_system.listen(timeout)
self.actor_system.tell(exec_actor, ActorExitRequest())
The actor_system is going to want to build instances of your class. That means it needs to be able to derive the class object- you cannot define it inside of a method.
If you really need to apply the decorator separately, you maybe could do
def launch(self, count, func_and_data, status_cb):
wrapped = troupe(max_count=count)(Executor)
exec_actor = self.actor_system.createActor(wrapped)

mocking an instance method of inner object in python 3.4

I have a class in my code that makes use of a third party library. I would like to mock the instance method of the object that I obtain by calling an instance method of the library class. I am not clear on how to mock the instance method of this inner object. Following is my code:
My class:
from a import A
class MyClass(object):
def __init__(self):
self.obj = A()
def do_something(self):
b = self.obj.get_inner_object()
result = b.do_inner()
return result
Here is my test class:
from unittest import TestCase
from unittest.mock import MagicMock
from unittest.mock import patch
from a import A
class TestMyClass(TestCase):
def __init__(self):
self.my_class = MyClass()
#patch.object(A,'get_inner_object')
def test_do_something(self, mock_get_inner_object):
test_res = self.my_class.do_something()
As you can see above, I would like to mock away 2 methods of my library - get_inner_object() and do_inner() which is the instance method of the object returned by get_inner_object(). I was able to mock get_inner_object(), but I am not clear on how to mock the do_inner() method. Please clarify. Here's the help I am following: https://www.toptal.com/python/an-introduction-to-mocking-in-python
Just mock out all of A:
#patch('a.A')
def test_do_something(self, mock_A):
mock_b = mock_A.return_value.get_inner_object.return_value
mock_b.do_inner.return_value = 'mocked return value'
test_res = self.my_class.do_something()
self.assertEqual(test_res, 'mocked return value')
After all, you are testing MyClass here, not A.
Either way, wether you use #patch.object(A, 'get_inner_object') or patch all of A, the self.obj.get_inner_object() expression calls a Mock instance, so the .return_value attribute is returned at that point. The do_inner method is just another chained call on that returned mock here, so you can set what is returned for that method by setting the .return_value attribute to something you test for.
To translate that back to your #patch.object() situation, mock_b is then the mock_inner_object.return_value object:
#patch.object(A,'get_inner_object')
def test_do_something(self, mock_get_inner_object):
mock_b = mock_get_inner_object.return_value
mock_b.do_inner.return_value = 'mocked return value'
test_res = self.my_class.do_something()
self.assertEqual(test_res, 'mocked return value')

Categories

Resources