dimanche 31 juillet 2016

Unittesting Django CreateView with mock library

I'm trying to test my CreateView by posting some data and mocking models' save() method.

class BaseViewTest(TestCase):
   def setUp(self):
       self.user = UserFactory()
       self.factory = RequestFactory()

class MuayeneCreateViewTest(BaseViewTest):

   def test_get(self):
        request = self.factory.get(reverse('muayene:create'))
        request.user = self.user

        response = MuayeneCreateView.as_view()(request)

        self.assertEqual(response.status_code, 200)
        self.assertTrue('form' in response.context_data)
        self.assertTrue('muayene/muayene_form.html' in response.template_name)

    @patch('muayene.models.Muayene.save', MagicMock(name="save"))
    def test_post(self):
        hasta = HastaFactory()
        ilac1 = IlacFactory()
        ilac2 = IlacFactory()
        data = {
            'hasta': hasta.id,
            'tarih': str(datetime.date.today()),
            'yakinma': 'Kusma',
            'kullandigi_ilaclar': [ilac1.id, ilac2.id],
            'öntani_tani': 'Öntanı ve tanı',
            'öneri_görüsler': 'Öneri ve Görüşler',
            'özel_notlar': 'Özel notlar'
        }

        request = self.factory.post(reverse('muayene:create'), data)
        request.user = self.user

        response = MuayeneCreateView.as_view()(request)

        self.assertEqual(response.status_code, 302)

        self.assertTrue(Muayene.save.called)
        self.assertEqual(Muayene.save.call_count, 1)

Here is MuayeneCreateView:

class MuayeneCreateView(LoginRequiredMixin, CreateView):
    login_url = '/login/'
    model = Muayene
    form_class = MuayeneCreateForm

and traceback:

ERROR: test_post (tests.test_muayene.MuayeneCreateViewTest)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/usr/lib64/python3.5/unittest/mock.py", line 1157, in patched
    return func(*args, **keywargs)
  File "/home/egegunes/Dropbox/Programs/hastatakip/tests/test_muayene.py", line 153, in test_post
    response = MuayeneCreateView.as_view()(request)
  File "/usr/lib/python3.5/site-packages/django/views/generic/base.py", line 68, in view
    return self.dispatch(request, *args, **kwargs)
  File "/usr/lib/python3.5/site-packages/django/contrib/auth/mixins.py", line 56, in dispatch
    return super(LoginRequiredMixin, self).dispatch(request, *args, **kwargs)
  File "/usr/lib/python3.5/site-packages/django/views/generic/base.py", line 88, in dispatch
    return handler(request, *args, **kwargs)
  File "/usr/lib/python3.5/site-packages/django/views/generic/edit.py", line 256, in post
    return super(BaseCreateView, self).post(request, *args, **kwargs)
  File "/usr/lib/python3.5/site-packages/django/views/generic/edit.py", line 222, in post
    return self.form_valid(form)
  File "/usr/lib/python3.5/site-packages/django/views/generic/edit.py", line 201, in form_valid
    self.object = form.save()
  File "/usr/lib/python3.5/site-packages/django/forms/models.py", line 452, in save
    self._save_m2m()
  File "/usr/lib/python3.5/site-packages/django/forms/models.py", line 434, in _save_m2m
    f.save_form_data(self.instance, cleaned_data[f.name])
  File "/usr/lib/python3.5/site-packages/django/db/models/fields/related.py", line 1618, in save_form_data
    setattr(instance, self.attname, data)
  File "/usr/lib/python3.5/site-packages/django/db/models/fields/related_descriptors.py", line 480, in __set__
    manager = self.__get__(instance)
  File "/usr/lib/python3.5/site-packages/django/db/models/fields/related_descriptors.py", line 468, in __get__
    return self.related_manager_cls(instance)
  File "/usr/lib/python3.5/site-packages/django/db/models/fields/related_descriptors.py", line 751, in __init__
    (instance, self.source_field_name))
ValueError: "<Muayene: ID: None - 2016-07-31 - Bob Baz>" needs to have a value for field "muayene" before this many-to-many relationship can be used.

I couldn't figure out what causes this error. Muayene instance is used by some other models with ManyToManyField but IMO this error must not show up unless I try to create one of those models with this instance.

Aucun commentaire:

Enregistrer un commentaire