I have a model, and I am trying to test validation without calling the database level. Instead of describing the words, I will simply post some code examples. The problem here is that ForeignKey’s attitude towards Bar, which is not related to what I'm trying to check, but stops me from running the test I want.
myapp/models.py :
from django.core.exceptions import ValidationError from django.db import models class BadFooError(ValidationError): pass class Bar(models.Model): description = models.CharField(max_length=20) class Foo(models.Model): bar = models.ForeignKey(Bar) a_value = models.IntegerField() b_value = models.BooleanField() def clean(self): super(Foo, self).clean() if self.b_value and self.a_value > 50: raise BadFooError("No good")
Next, myapp/tests.py :
from unittest import TestCase from mock import MagicMock from . import models class SimpleTest(TestCase): def test_avalue_bvalue_validation(self): foo = models.Foo() foo.a_value = 30 foo.b_value = True foo.bar = MagicMock(spec=models.Bar) self.assertRaises(models.BadFooError, foo.full_clean) def test_method_2(self): foo = models.Foo() foo.a_value = 30 foo.b_value = True foo.bar = MagicMock() foo.__class__ = models.Bar self.assertRaises(models.BadFooError, foo.full_clean) def test_method_3(self): foo = models.Foo() foo.a_value = 30 foo.b_value = True
Finally, the output of python manage.py test myapp
EEE ====================================================================== ERROR: test_avalue_bvalue_validation (myapp.tests.SimpleTest) ---------------------------------------------------------------------- Traceback (most recent call last): File "~/sandbox/myapp/tests.py", line 14, in test_avalue_bvalue_validation foo.bar = MagicMock(spec=models.Bar) File "~/dsbx/local/lib/python2.7/site-packages/django/db/models/fields/related.py", line 408, in __set__ instance._state.db = router.db_for_write(instance.__class__, instance=value) File "~/dsbx/local/lib/python2.7/site-packages/django/db/utils.py", line 142, in _route_db return hints['instance']._state.db or DEFAULT_DB_ALIAS File "~/dsbx/local/lib/python2.7/site-packages/mock.py", line 658, in __getattr__ raise AttributeError("Mock object has no attribute %r" % name) AttributeError: Mock object has no attribute '_state' ====================================================================== ERROR: test_method_2 (myapp.tests.SimpleTest) ---------------------------------------------------------------------- Traceback (most recent call last): File "~/sandbox/myapp/tests.py", line 21, in test_method_2 foo.bar = MagicMock() File "~/dsbx/local/lib/python2.7/site-packages/django/db/models/fields/related.py", line 405, in __set__ self.field.name, self.field.rel.to._meta.object_name)) ValueError: Cannot assign "<MagicMock id='31914832'>": "Foo.bar" must be a "Bar" instance. ====================================================================== ERROR: test_method_3 (myapp.tests.SimpleTest) ---------------------------------------------------------------------- Traceback (most recent call last): File "~/sandbox/myapp/tests.py", line 29, in test_method_3 self.assertRaises(models.BadFooError, foo.full_clean) File "/usr/lib/python2.7/unittest/case.py", line 471, in assertRaises callableObj(*args, **kwargs) File "~/dsbx/local/lib/python2.7/site-packages/django/db/models/base.py", line 926, in full_clean raise ValidationError(errors) ValidationError: {'bar': [u'This field cannot be null.']} ---------------------------------------------------------------------- Ran 3 tests in 0.003s FAILED (errors=3) Creating test database for alias 'default'... Destroying test database for alias 'default'...
So my question is ... wat do?