Исправить переменную внутри метода экземпляра класса - PullRequest
0 голосов
/ 23 октября 2018

Я пытаюсь понять, как работает исправление, и я тестирую с pytest a Django View:

views.py

from django.contrib.auth.views import LoginView

class MyLoginView(LoginView):
    pass

test_view.py

from django.test import RequestFactory
from .views import MyLoginView

rf = RequestFactory()

def test_login(rf):
    request = rf.get(reverse('myapp:login'))
    response = MyLoginView.as_view()(request)
    assert response.status_code == 200

Это не удается, потому что это представление вызывает базу данных для получения текущего сайта, используя функцию get_current_site():

Failed: Database access not allowed

Как я могу издеваться get_current_site() чтобы избежать попадания в базу данных?

Идея состоит в том, чтобы использовать фабрику с pytest-factoryboy.

Мне удалось высмеять LoginView.get_context_data, но я не могу идти глубже:

from django.test import RequestFactory
from .views import MyLoginView

from django.contrib.sites.models import Site
from pytest_factoryboy import register
from unittest.mock import patch

rf = RequestFactory()


class SiteFactory(factory.Factory):
    class Meta:
        model = Site

register(SiteFactory)


def test_login_social(rf, site_factory):
    request = rf.get(reverse('myapp:login'))
    with patch(
        # 'django.contrib.auth.views.LoginView.get_context_data',  # This is wrong
        'django.contrib.auth.views.get_current_site',  # Solution: Patch where it is imported, this works!
        return_value=site_factory(name='example.com'),
    ):
        response = CommunityLoginView.as_view()(request)
    assert response.status_code == 200

Редактировать

Решение заключается в исправлении вызываемого метода в области, в которой он импортируется :

with patch('django.contrib.auth.views.get_current_site')


Здесь возникает ошибка из-за того, что context_data является <class 'django.contrib.sites.models.Site'>

Как бы вы это сделали?

1 Ответ

0 голосов
/ 24 октября 2018

У вас есть две опции:

  1. pytest разрешает доступ к базе данных только в том случае, если вы явно отметите тестовую функцию, что мы попадем в базу данных.Без этой информации pytest запустит тест, не создав базу данных для тестов.Я рекомендую использовать pytest-django и предоставленный декоратор pytest.mark.django_db.

  2. Вы добавили Site-Framework к вашему INSTALLED_APPS.Это приложение не является обязательным, но полезно, если вы обслуживаете несколько разных страниц из одного приложения Django.Было время, когда Site-Framework был обязательным, но так как он необязательный, я редко включаю в свой INSTALLED_APPS.Может быть, вы должны оставить это для.


РЕДАКТИРОВАТЬ: Насмешка

Конечно, насмешка должна работать, так как каждый объект вПитон является насмешливым ( даже маленькие цифры ).Имейте в виду, что вам необходимо установить, куда импортируется модуль / функция , поскольку он привязан к локальной области.

Чтобы найти правильное местоположение, вы можете выполнить поиск в Django.исходный код , посмотрите, как он используется и как правильно его исправить или попробуйте зайти в PDB.Я не уверен, какой способ будет работать, но я предоставляю вам 2 варианта:

  1. pytest --pdb
  2. python -m pdb pytest.Это мгновенно откроет отладчик, и вам придется один раз continue.pytest теперь будет работать до тех пор, пока не произойдет первое исключение, и PDB не запустится автоматически.

Теперь вы можете использовать bt (backtrace), u (walk stack up), l (показать исходный код) и d (пройти вниз по стеку), чтобы найти место доступа к базе данных.


EDIT2: factoryboy

Если выfactoryboy, это зависит от стратегии построения 1067 *, пытается ли он получить доступ к базе данных или нет.Стратегия по умолчанию - .create(), которая записывает в базу данных.

Она должна работать, если вы используете site_factory.build(), так как это не будет обращаться к вашей базе данных.

...