Вручную получить ответ из общего представления на основе классов

Я пытаюсь написать тест, который проверяет HTML, возвращаемый из общего представления на основе классов. Допустим, у меня есть представление на основе функций, которое просто отображает шаблон:

# views.py
from django.shortcuts import render

def simple_view(request, template='template.html'):
    return render(request, template)

При этом во время тестирования я могу просто сделать:

# tests.py
from django.http import HttpRequest
from .views import simple_view

request = HttpRequest()
response = simple_view(request)

а затем выполните проверку на response. Теперь я хотел бы преобразовать приведенное выше представление в представление на основе классов, наследуемое от TemplateView:

# views.py
from django.views.generic import TemplateView

class SimpleView(TemplateView):
    template_name = 'template.html'

Теперь, по сути, тот же метод тестирования не работает:

# tests.py
from django.http import HttpRequest
from .views import SimpleView

request = HttpRequest()
view_func = SimpleView.as_view()
response = view_func(request).render()

приводит к

Traceback (most recent call last):
    File "tests.py", line 30, in test_home_page_returns_correct_html
response = view_func(request).render()
    File "lib/python2.7/site-packages/django/views/generic/base.py", line 68, in view
return self.dispatch(request, *args, **kwargs)
    File "lib/python2.7/site-packages/django/views/generic/base.py", line 82, in dispatch
if request.method.lower() in self.http_method_names:
AttributeError: 'NoneType' object has no attribute 'lower'

Я попытался установить request.method вручную на GET, но это просто вызывает еще одну ошибку, жалующуюся на то, что session не находится в request.

Есть ли способ получить ответ от TemplateView с «пустым» запросом?


person Maciej Gryka    schedule 21.04.2013    source источник
comment
stackoverflow.com/questions/8603035/   -  person dm03514    schedule 21.04.2013


Ответы (2)


Спасибо dm03513 за подсказки! Действительно, мне пришлось использовать RequestFactory, но также убедиться, что request содержит пустой session (несмотря на то, что SessionMiddleware указан первым):

# tests.py
from django.test import TestCase
from django.test.client import RequestFactory

class SimpleTest(TestCase):
    def setUp(self):
        self.factory = RequestFactory()

    def test_home_page_returns_correct_html(self):
        request = self.factory.get('/')
        request.session = {}
        view_func = SimpleView.as_view()
        response = view_func(request)
        response.render()
        self.assertIn('<html>', response.content)
person Maciej Gryka    schedule 21.04.2013
comment
request.session = {} не прошел мое тестирование. Я установил сеанс по запросу следующим образом, и он сработал (конечно, сначала импортируйте модули по мере необходимости): request.session = django.utils.importlib.import_module(django.conf.settings.SESSION_ENGINE).SessionStore(None) Я объединил ваш ответ с ответом на этот вопрос. - person dmmfll; 20.06.2014

Вы можете использовать djangos, встроенный в тест client для выполнения это вместо создания экземпляра и вызова представления напрямую

тестовый клиент позволяет вам сделать запрос через URL-адрес маршрутизатора django

response = self.get('/url/to/invoke/simpleview/')

Кроме того, я нашел пару сообщений в блогах о том, как тестировать представления на основе классов, одно из которых http://tech.novapost.fr/django-unit-test-your-views-en.html

person dm03514    schedule 21.04.2013
comment
Правда, как указано здесь: stackoverflow.com/questions/8603035/, которые более функциональны, чем модульный тест (вы имитируете браузер, а не просто играете с функциями). Я думаю, в данном случае это не имеет большого значения, но хорошо знать, что оба варианта возможны! - person Maciej Gryka; 21.04.2013
comment
С другой стороны, использование клиента в этом случае, вероятно, является более разумным, если не единственным способом! - person Maciej Gryka; 22.04.2013