Reputation: 85
I'm trying to override a custom Django model property via factory_boy
for testing purposes. But it seems like it is simply taking the default behavior of the model. is factory boy not able to change the default behaviour of custom attributes?
Here is a basic test I wrote:
models.py:
class Session(models.Model):
name = models.CharField(max_length=100)
@property
def foo(self):
return method_not_callable_in_testing()
def method_not_callable_in_testing():
return 42
SessionFactory.py:
class SessionFactory(factory.django.DjangoModelFactory):
class Meta:
model = Session
name = "session"
foo = 1337
tests.py: class TestSession(TestCase):
def test_custom_attribute_overwritten_by_factoryboy(self):
session = SessionFactory.create()
self.assertEquals(session.foo, 1337)
When running the tests I get the following error:
F
======================================================================
FAIL: test_custom_attribute_overwritten_by_factoryboy (bar.tests.TestSession)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/home/sh4ke/repos/foo/bar/tests.py", line 10, in test_custom_attribute_overwritten_by_factoryboy
self.assertEquals(session.foo, 1337)
AssertionError: 42 != 1337
Upvotes: 4
Views: 2211
Reputation: 8159
factory_boy can change "custom attributes", (which I assume you mean ones that are not django Fields
), but it can't change read-only attributes, which is what you are trying to do.
Your problem is that you are trying to use the factory to set an attribute for a read-only property. Roughly, the combination of factory_boy and django means that the call to SessionFactory()
is doing:
session = Session()
session.foo = 1337
But I wouldn't expect this to work because unless you declare the @foo.setter
method @property
assumes you wanted a read-only property, and so raises attribute error when you attempt to set it.
The weird bit is why you don't see that error, and it turns out that django quietly suppresses it! It sees that your model has the foo
attribute by doing getattr(session, 'foo')
, but it has wrapped the whole thing including the setattr
inside a try: except AttributeError:
, so while it detects and raises an attempt to set an attribute that doesn't exist at all, it also catches and quietly ignores the failed case of an attempt to set a read-only property.
I suspect this is a bug... so will probably try and raise it with the django community.
Upvotes: 1