简体   繁体   中英

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')

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM