Skip to content
Advertisement

mocking/patching the value of a computed attribute from a classmethod

I am attempting to write a test for a function which calls an object’s classmethod — this classmethod goes on to return a new instance of that class.

There are plenty of examples of patching class attributes both here on stackoverflow and elsewhere but I am having difficulty understanding how to patch attribute/value such that I can test my function. I’ve referred to this answer.

Essentially I am trying to patch the attribute xxxx of the instance of Foo (within myFn) so that I can test/assert the subsequent value from its call to some_other_function()

The code below is standalone a ‘runnable’ of the problem: I’m getting an AttributeError: Foo doesn’t have the attribute ‘xxxx’

import time
import unittest
from unittest.mock import patch, PropertyMock

class Foo(object):
    def __init__(self, xxxx):
        """long running task"""
        time.sleep(5)
        self.xxxx = xxxx

    @classmethod
    def get(cls):
        """also a long running task"""
        time.sleep(5)
        xxxx = 555
        return cls(xxxx)

def myFn():
    v = Foo.get().xxxx
    # the patched `xxxx` should be 666 at this point
    return some_other_function(v)

class Test(unittest.TestCase):

    @patch('__main__.Foo', autospec=True)
    def test_myFn(self, mock_Foo):
        with patch('__main__.Foo.xxxx', new_callable=PropertyMock, return_value=666):
            x = myFn()
            self.assertEqual(x, 666)

if __name__ == '__main__':
    unittest.main()

Very grateful for anyone’s help!

Advertisement

Answer

You should use the create parameter that will force the creation of the attribute if it does not exist:

def test_myFn(self):
    with patch('__main__.xxxx', new_callable=PropertyMock, create=True, return_value=666):
        x = myFn()
        self.assertEqual(666,x)
User contributions licensed under: CC BY-SA
4 People found this is helpful
Advertisement