2013-05-30 4 views
6

मेरे पास एक मॉडल है और मैं डेटाबेस परत का आविष्कार किए बिना सत्यापन का परीक्षण करने की कोशिश कर रहा हूं। शब्दों के साथ वर्णन करने के बजाय मैं बस कुछ उदाहरण कोड पोस्ट करूंगा। यहां मुद्दा यह है कि बार के लिए विदेशीकी संबंध है, जो कि मैं परीक्षण करने की कोशिश कर रहा हूं उससे प्रासंगिक नहीं है लेकिन मुझे वह परीक्षण चलाने से रोक रहा है जो मैं चाहता हूं।एक Django ForeignKey मान नकल करने के लिए नकली पुस्तकालय का उपयोग कैसे करें?

पहले, 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") 

इसके बाद, 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 
     # ignore it and it will go away ...?? 
     self.assertRaises(models.BadFooError, foo.full_clean) 

अन्त में, 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'... 

तो मेरे सवाल ... वाट कर रहा है के उत्पादन में?

उत्तर

0

ठीक है, अभी के लिए मैंने self.assertRaises(models.BadFooError, foo.clean) पर अपना जोर बदल दिया है (के स्थान पर foo.clean अंतर)। जबकि यह काम करता है, यह आदर्श प्रतीत नहीं होता है। मैं एक ब्लैक बॉक्स के रूप में सत्यापन का परीक्षण करना चाहता था।

4

मेरी इकाई परीक्षण में, मैं बस _state एक नया नकली उदाहरण के लिए, आवंटित अपना पहला उदाहरण इकाई परीक्षण को यह छोटा सा परिवर्तन के रूप में:

def test_avalue_bvalue_validation(self): 
    foo = models.Foo() 
    foo.a_value = 30 
    foo.b_value = True 
    bar = Mock(spec=models.Bar) 
    bar._state = Mock() 
    foo.bar = bar 
    self.assertRaises(models.BadFooError, foo.full_clean) 

हालांकि, एक ब्लैक बॉक्स के रूप में अपने सत्यापन परीक्षण करने के लिए, मैं सत्यापन मॉडल को आपके मॉडल पर एक अलग विधि में खींच देगा जिसे मैं clean() विधि के अंदर से कॉल करूंगा। फिर आप इकाई को इस सत्यापन कोड का विशेष रूप से परीक्षण कर सकते हैं। आपको अभी भी _stage = Mock() असाइनमेंट करने की आवश्यकता होगी ताकि आप फू का अपना उदाहरण बना सकें, लेकिन कम से कम आप Django में कॉल को कम कर देंगे।

संबंधित मुद्दे