这有效
def test_access_to_home_with_location(self):
self.client.login(username=self.user.get_username(), password='pass')
session = self.client.session
session['location'] = [42]
session.save()
response = self.client.get(reverse('home'))
但是这个
def test_access_to_home_with_location(self):
session = self.client.session
session['location'] = [42]
session.save()
response = self.client.get(reverse('home'))
打破
======================================================================
ERROR: test_access_to_home_with_location (posts.tests.HomeViewTestCase)
----------------------------------------------------------------------
Traceback (most recent call last):
File "tests.py", line 32, in test_access_to_home_with_location
session.save()
AttributeError: 'dict' object has no attribute 'save'
所以似乎没有调用self.client.login()
self.client.session
只是一个空字典。有没有办法将其初始化为会话对象?
答案 0 :(得分:7)
如果客户端没有设置cookie,则session
属性为空字典,因此您的错误。以下是django.test.client.Client
的相关来源:
def _session(self):
"""
Obtains the current session variables.
"""
if 'django.contrib.sessions' in settings.INSTALLED_APPS:
engine = import_module(settings.SESSION_ENGINE)
cookie = self.cookies.get(settings.SESSION_COOKIE_NAME, None)
if cookie:
return engine.SessionStore(cookie.value)
return {}
session = property(_session)
由于您未使用匹配settings.SESSION_COOKIE_NAME
的密钥登录cookie,因此未找到。
但是你可以手动创建一个这样的会话对象:
if not self.client.session:
engine = import_module(settings.SESSION_ENGINE)
self.client.session = engine.SessionStore()
self.client.session.save()
这是login
中Client
处理程序创建新会话的方式。
编辑:我意识到您还需要将会话密钥保存在Cookie中,以便下一个请求使用相同的会话
这是一个辅助函数,你可以放在Client
子类中创建一个新会话和一个引用cookie:
def set_session_data(self, key, value):
"""Shortcut for setting session data regardless of being authenticated"""
if not self.client.session:
# Save new session in database and add cookie referencing it
engine = import_module(settings.SESSION_ENGINE)
self.client.session = engine.SessionStore()
self.client.session.save()
session_cookie = settings.SESSION_COOKIE_NAME
self.client.cookies[session_cookie] = self.client.session.session_key
cookie_data = {
'max-age': None,
'path': '/',
'domain': settings.SESSION_COOKIE_DOMAIN,
'secure': settings.SESSION_COOKIE_SECURE or None,
'expires': None,
}
self.client.cookies[session_cookie].update(cookie_data)
self.client.session[key] = value
self.client.session.save()
注意:我不是说这是唯一的方法,这是我通过阅读django源代码发现的一种方式。此答案中的代码未经过测试/运行,因此可能需要进行一些微调。
要了解SessionStore
的工作原理,您可以查看django.contrib.sessions
模块。
要了解如何在Client
中处理会话和Cookie,您可以查看django.test.client.Client
。
答案 1 :(得分:3)
rzetterberg答案是更严格的答案,所以我认为它应该保持被接受,但这种方式看起来也会起作用
def setUp(self):
"""
set up sessions for anonymous users
"""
engine = import_module(settings.SESSION_ENGINE)
store = engine.SessionStore()
store.save()
self.client.cookies[settings.SESSION_COOKIE_NAME] = store.session_key
看起来这个主题上有一张当前的票据(5年前开始......但在最近几个月内有效):
https://code.djangoproject.com/ticket/10899
和
https://code.djangoproject.com/ticket/11475
答案 2 :(得分:3)
请注意,不再需要解决方法。原始问题的片段不起作用现在应该有效:
session = self.client.session
session['location'] = [42]
session.save()
https://docs.djangoproject.com/en/2.0/topics/testing/tools/#django.test.Client.session
答案 3 :(得分:0)
我使用RequestFactory
生成request
对象,手动设置会话值,并将其传递给视图函数,如docs中所示。
from django.test import TestCase, RequestFactory
from django.urls import reverse
from .views import test_view
class MyTestCase(TestCase):
def setUp(self):
self.factory = RequestFactory()
def test_view_x(self):
request = self.factory.get(reverse('myapp:test_view'))
request.session = {'foo': 'bar'}
response = test_view(request)
...
# Run some test on the response to ensure the view is returning
# the expected value
使用RequestFactory
生成请求对象可以测试视图函数,就像测试任何其他函数一样 - 将其视为黑盒子,传递某些输入并检查正确的输出。请注意,您单独运行请求,没有任何已安装的中间件。