Skip to content Skip to sidebar Skip to footer

Python: Mock Side_effect On Object Attribute

Is it possible to have a side_effect on a property? If I look at the Mock documentation it seems it's only possible on object methods. I am trying to test the following: def get_ob

Solution 1:

It's worth noting that there is now the PropertyMock class:

>>>m = MagicMock()>>>p = PropertyMock(side_effect=ValueError)>>>type(m).foo = p>>>m.foo
Traceback (most recent call last):
....
ValueError

That example was taken from the official site.

Solution 2:

You can also try to patch the related field using a PropertyMock as new_callable argument.

Example:

from unittest import TestCase
import mock
from django import models
from django.core.exceptions import ObjectDoesNotExist

classFoo(models.Model):
    # ...    @propertydefhas_pending_related(self):
        try:
            return self.related_field.is_pending
        except ObjectDoesNotExist:
            returnFalseclassFooTestCase(TestCase):
    # ...    @mock.patch.object(Foo, 'related_field', new_callable=mock.PropertyMock)deftest_pending_related(self, related_field):
        related_field.side_effect = ObjectDoesNotExist
        foo = Foo()
        self.assertFalse(foo.has_pending_related)

Solution 3:

Yes, you can use a property for it:

In [1]: classShopDoesNotExist(Exception):
   ...:     pass
   ...:

In [2]: classUser(object):
   ...:     @property
   ...:     defshop(self):
   ...:         raise ShopDoesNotExist
   ...:
   ...:

In [3]: u = User()

In [4]: u.shop
---------------------------------------------------------------------------
ShopDoesNotExist                          Traceback (most recent call last)

Solution 4:

The author made a blog post about this problem. I went for the first solution which looks like this:

classUserMock(Mock):
    @propertydefshop(self):
        raise Shop.DoesNotExist()

http://www.voidspace.org.uk/python/weblog/arch_d7_2010_11_20.shtml#e1196

Solution 5:

As an aside, if you're trying to test for AttributeError as an side_effect you can use spec parameter and set it to empty list (i.e. []). Say you're trying to create a Mock object that throws an AttributeError when accessing attribute foo:

from unittest.mock import Mock
m = Mock(spec = [])
m.foo

# AttributeError: Mock object has no attribute 'foo'

See Documentation:

spec: This can be either a list of strings or an existing object (a class or instance) that acts as the specification for the mock object. If you pass in an object then a list of strings is formed by calling dir on the object (excluding unsupported magic attributes and methods). Accessing any attribute not in this list will raise an AttributeError.

Post a Comment for "Python: Mock Side_effect On Object Attribute"