您的问题主要归结为在您的测试请求中提供会话令牌。如果您不提供令牌,则会话为空白。
我假设您的实际应用程序正在正确发送会话令牌,因此似乎可以工作。
修复测试用例无需太多时间即可正确通过。
每个请求都尝试根据 post 参数加载会话
在你的会话实现中:
def open_session(self, app, request):
s = Session()
if 't' in request.form:
....
return s
这意味着每个不是POST(或PUT)且没有t发送的请求将
有一个空白会话。
而基于 cookie 的实现将始终具有可用的会话令牌
并且能够加载以前请求的会话。
这是您的一个示例测试:
def test_authorize_captcha_expired(self):
with self.client as c:
with c.session_transaction() as s:
s['captcha-answer'] = u'one two three'.split()
s['captcha-expires'] = datetime.today() - timedelta(minutes=1)
self.assertEqual(c.post('/test', data={
'ca': 'one two three',
}).status_code, 400)
您尚未为/test 的帖子提供t 值。因此它得到一个空白
没有captcha-expires 键和KeyError 的会话被引发。
您的会话需要一个“令牌”密钥才能保存
在你的会话实现中:
def save_session(self, app, session, response):
if session.modified and 'token' in session:
...
# save session to database
...
因此当你有:
with c.session_transaction() as s:
s['captcha-answer'] = u'one two three'.split()
s['captcha-expires'] = datetime.today() - timedelta(minutes=1)
实际上没有会话被写入数据库。对于任何后续请求
采用。请注意,它确实确实需要写入数据库,因为open_session 将尝试在每次请求时从数据库中加载某些内容。
要解决大多数情况,您需要在创建会话时提供一个“令牌”,并为使用它的任何请求提供一个带有该令牌的“t”。
因此,我上面使用的示例测试最终会是:
def test_authorize_captcha_expired(self):
with self.client as c:
token = generate_key(SystemRandom())
with c.session_transaction() as s:
s['token'] = token
s['captcha-answer'] = u'one two three'.split()
s['captcha-expires'] = datetime.today() - timedelta(minutes=1)
self.assertEqual(c.post('/test', data={
'ca': 'one two three',
't': token
}).status_code, 400)
用 json 响应时更改令牌
...但是当您发出后续请求时,您没有使用新令牌
def test_reply_to_reflection_passthrough(self):
with self.client as c:
token = 'abcdef'
...
response2 = c.post('/reflection/1/reply', data={
'p': 'test4',
'r': 'testmessage',
't': token,
}, ...
到这里,/reflection/1/reply 的帖子生成了一个新的
令牌并保存它,因此关键密钥last-reply 不在
由abcdef 标识的会话。如果这是一个基于 cookie 的会话,那么 last-reply 将可用于下一个请求。
所以要修复这个测试...使用新令牌
def test_reply_to_reflection_passthrough(self):
with self.client as c:
...
response2 = c.post('/reflection/1/reply', data={
...
token = session['token']
with c.session_transaction(method="POST", data={'t':token}) as s:
s['token'] = token
s['last-request'] = datetime.now() - timedelta(milliseconds=1001)
response3 = c.post('/reflection/1/reply', data={
...
重定向会丢失会话令牌
在测试中test_bump:
def test_bump(self):
response = self.client.post(
'/admin/tip/action/',
data = {'action': 'Bump', 'rowid': '1',},
follow_redirects=True )
self.assertIn(' tips have been bumped.', response.data)
/admin/tip/action 的帖子返回重定向。
在这里,您正在检查是否存在 Flash 消息。和闪信息
存储在会话中。
对于基于 cookie 的会话,会话 ID 会在后续重定向请求中再次发送。
由于您的会话 id 被指定为 post 值,因此不会再次发送,会话和 flash 消息都会丢失。
解决这个问题的方法不是跟随重定向,而是通过烧瓶闪存方法检查会话中的数据集。
def test_bump(self):
with self.client as c:
token = generate_key(SystemRandom())
with c.session_transaction() as s:
s['token'] = token
c.post('/admin/tip/action/',
data={'action': 'Bump', 'rowid': '1', 't': token})
with c.session_transaction(method="POST", data={'t': token}) as s:
self.assertIn(' tips have been bumped.', s['_flashes'][0][1])
仅此而已
我已经发送了一个包含上述更改的拉取请求,您会发现默认烧瓶会话和您的会话实现的测试现在都通过了。