Damo
Damo

Reputation: 384

python mock class attributes are not accessible

When mocking a class object I can't access it's attributes. I've read a lot of documentation but I'm new to mocking and don't see the problem with this code. I expect x and y to return the same value 1e-15

class test_user_data:
    scale = 1e-15

class test_signal(unittest.TestCase):
    @patch('xx.user_data', autospec=test_user_data, spec_set=True)
    def test_data(self, mock_user_data):
        x = xx.user_data()
        y = test_user_data()
        print(x.scale)
        print(y.scale)

but I get

<NonCallableMagicMock name='user_data().timescale' spec_set='float' id='47213638195072'>
1e-15

Upvotes: 3

Views: 6226

Answers (1)

wholevinski
wholevinski

Reputation: 3828

autospec and spec'ing in general is used to define an API. When using a Mock, you can pretty much call or access any attribute on it and it'll just let you. It will return another mock object though.

See something like this:

>>> my_mock = Mock()
>>> my_mock.stuff
<Mock name='mock.stuff' id='139870989908344'>
>>> my_mock.junk()
<Mock name='mock.junk()' id='139870987197912'>

If I define a spec, it says you can't access things that don't actually exist on the real class. Like so:

>>> my_mock = Mock(spec=xx.user_data)
>>> my_mock.stuff
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib64/python3.4/unittest/mock.py", line 574, in __getattr__
    raise AttributeError("Mock object has no attribute %r" % name)
AttributeError: Mock object has no attribute 'stuff'
>>> my_mock.scale
<Mock name='mock.scale' id='139871128095264'>

So the above shows you can't access an attribute on the Mock that isn't defined in the actual user_data class because I've used spec.

That explains how autospec works, but what you actually want is the return_value arg. Go ahead and add it to your patch decorator and you should be all set. It should look like this:

@patch('xx.user_data', autospec=test_user_data, spec_set=True, return_value=test_user_data)

Upvotes: 1

Related Questions