Форма для насмешек в представлении на основе классов без использования MagicMock - PullRequest
0 голосов
/ 10 января 2019

Я боролся с насмешкой над классом формы, чтобы заменить его экземпляр в представлении на основе классов. Но похоже, что так как форма находится в атрибуте класса, это происходит за до . Я заменяю класс формы своим макетом. Показательный пример:

приложение / views.py

from app.forms import SomeForm  # For some reason, this _is_ my mock...

class SomeViewClass(View):
    form = SomeForm  # ... while this is the _real_ SomeForm

    def post(self, request):
        form = self.form(request.POST, request.FILES)

        # Hacked around with pdb here
        # (Pdb) self.form = SomeForm <-- Force the mock into the object
        # (Pdb) form = self.form(request.POST, request.FILES)
        # (Pdb) form.is_valid() is now True
        # (Pdb) continue <--- Test finishes, and asserts are OK.

        if form.is_valid():  # This fails, as I'm running the real code
            # code, code, code

Приложение / тесты / test_views.py

from mock import MagicMock, patch

from django.tests import Client, TestCase


@patch('app.views.SomeForm')
    def test_post_valid_form_should_pass(self, mocked_form_class):
        """ Replacing SomeForm in SomeViewClass to pas the is_valid test
        """
        form_instance = MagicMock(spec=SomeForm())
        form_instance.is_valid.return_value = True
        mocked_form_class.return_value = form_instance

        self.client.login(**self.credentials)
        # code, code, code

Как вы можете видеть во вставленных комментариях в app/views.py, я принудительно перезагрузил self.form и переопределил переменную form, используя pdb, что и сделало мой тест успешным.

По какой-то причине SomeViewClass [зарегистрировано, инстанцировано, ...] до того, как я начну исправлять SomeForm. Есть идеи на этот счет?

1 Ответ

0 голосов
/ 11 января 2019

Проблема в том, что представление уже загружено Django, а поле form уже определено и указывает на класс SomeForm production .

Как отметили @DanielRoseman и @foxyblue в своих комментариях, можно напрямую пропатчить поле в классе. И на самом деле уже был ответ для этого на SO . Как уже указывалось, можно использовать patch.object для исправления члена класса (что, IMO, лучшее решение, поскольку оно более явное и менее подвержено опечаткам)

Тест исправлен:

С patch

@patch('app.views.SomeView.form', autospec=SomeForm)
    def test_post_valid_form_should_pass(self, mocked_form_class):
        """ Replacing SomeForm in SomeViewClass.form to pass the is_valid test """
        mocked_form_class.is_valid.return_value = True

        self.client.login(**self.credentials)
        # code, code, code

С patch.object

@patch.object(SomeView, 'form', autospec=SomeForm)
    def test_post_valid_form_should_pass(self, mocked_form_class):
        """ Replacing SomeForm in SomeViewClass.form to pass the is_valid test """
        mocked_form_class.is_valid.return_value = True

        self.client.login(**self.credentials)
        # code, code, code
...