run_the_race
run_the_race

Reputation: 2408

Python unittest Mock an object to not have an attribute

I have a function that runs some code if the object has a certain attribute, and in rare cases if if the object does not have the attribute, it runs different code. It is hard for me to create the object without the attribute for testing. I tried del instance.attribute but got an error. The attribute is actually a @property under the hood.

I have an object instance that has foo attribute. How does one mock it so that when one tries to access instance.foo it raises an AttributeError as usual if there is no attribute?

I tried mock.Mock(side_effect=AttributeError('Boom!')) but it only works with methods.

Upvotes: 2

Views: 3010

Answers (1)

MrBean Bremen
MrBean Bremen

Reputation: 16855

You could try to use a PropertyMock for the property, and generally you shall be able to set the respective side effect. Here is a simple working example:

from unittest import mock
import pytest

class Foo:
    @property
    def bar(self):
        return "bar"


def test_no_foo():
    bar_mock = mock.PropertyMock()
    with mock.patch(f"{__name__}.Foo.bar", bar_mock):
        bar_mock.side_effect = AttributeError('Boom!')
        foo = Foo()
        with pytest.raises(AttributeError):
            foo.bar

As you patch the property in the class, not in the object, you can can also do this using patch.object if you have access to the object by accessing the class of the object:

def test_no_foo():
    bar_mock = mock.PropertyMock()
    foo = Foo()
    with mock.patch.object(foo.__class__, "bar", bar_mock):
        bar_mock.side_effect = AttributeError('Boom!')
        with pytest.raises(AttributeError):
            foo.bar

Upvotes: 3

Related Questions