无法使用 Jest、Supertest、Passport、Koa2 在测试中发送经过身份验证的请求
Unable to send authenticated request in tests using Jest, Supertest, Passport, Koa2
尽管我尽最大努力正确编写测试代码来验证设置块或之前的 describe/it 块中的请求代理,但我在后续 describe/it 块中从代理发出的任何请求都无法完成,因为 200 .
示例代码:
const request = require('supertest');
const server = require('../server');
let agent = request.agent(server);
let fakePerson = null;
beforeEach(async (done) => {
fakePerson = await Person.createMock();
agent.post(‘/login’)
.send({
email: ‘test@user.com’,
password: ‘password’
})
.end(function(err, res) {
if (err) throw err;
done();
});
});
describe('GET /users/:id', () => {
it ('renders user profile', () => {
return agent
.get(`/users/${fakePerson.id}`)
.expect(200)
});
});
我认为这可能与我在语法上形成异步调用的方式有关。但是在尝试使用 return
、.end()
语法在 beforeEach
块中返回登录调用的不同方式后,甚至 async/await,我已经确定(即放弃)代码必须正确组合。会不会是别的东西?
引用articles/resources:
- How to authenticate Supertest requests with Passport?
- https://medium.com/@juha.a.hytonen/testing-authenticated-requests-with-supertest-325ccf47c2bb
- https://gist.github.com/joaoneto/5152248
- https://medium.com/@bill_broughton/testing-with-authenticated-routes-in-express-6fa9c4c335ca
- https://github.com/visionmedia/supertest/issues/46
包版本:
- "koa": "^2.4.1"
- "koa-passport": "^4.0.1"
- "passport-json": "^1.2.0"
- "passport-local": "^1.0.0"
- "supertest": "^3.0.0"
- "jest": "^22.1.3"
我在测试运行期间花了一些时间逐步检查我的授权代码,但没有发现任何明显的问题。然后我有一个想法:如果请求本身格式不正确怎么办。事实证明我是对的!检查超测响应 header 中的 set-cookie
header 我看到:
[ 'koa:sess=eyJwYXNzcG9ydCI6eyJ1c2VyIjoxfSwiX2V4cGlyZSI6MTUyMTIyODg0NTU5OSwiX21heEFnZSI6ODY0MDAwMDB9; path=/; httponly,koa:sess.sig=EEZzgcg3bx8bm_FXRMobrr8_Yts; path=/; httponly' ]
作为单个字符串,这看起来有点可疑,这让我进行了更多谷歌搜索,我发现在为 Mocha 和 Jest 用户设置 cookie headers 的方式上存在差异作为全局Supertest 代理实例上的状态。请参阅:https://github.com/facebook/jest/issues/3547#issuecomment-302541653. Folks using Mocha had no trouble authenticating, while Jest users did. Turns out there is a bug Jest 全局变量导致 cookie 以单个字符串形式出现,而不是每个 cookie 的单独字符串数组——这是 Supertest 正确格式化请求所需要的。
这是一个基于问题中代码的变通方法,我们在其中正确地将有问题的 Jest 字符串解析为 Setup 块内 cookie/session 数据的作用域变量:
const request = require('supertest');
const server = require('../server');
let agent = request.agent(server);
let fakePerson = null;
let session = null;
beforeEach(async () => {
fakePerson = await Person.createMock();
agent.post(‘/login’)
.send({
email: fakePerson.email,
password: fakePerson.password’
})
.then(res => {
session = res
.headers['set-cookie'][0]
.split(',')
.map(item => item.split(';')[0])
.join(';')
expect(res.status).toEqual(200)
});
});
describe('GET /users/:id', () => {
it ('renders user profile', () => {
return agent
.get(`/users/${fakePerson.id}`)
.set('Cookie', session)
.expect(200)
});
});
我无法得到 internetross 的答案。经过大量调查,我终于找到了这个:https://github.com/facebook/jest/issues/3547#issuecomment-397183207.
我不得不更换
session = response.headers['set-cookie'][0]
.split(',')
.map(item => item.split(';')[0])
.join('; ')
和
response.headers['set-cookie'][0]
.split(',')
.map(item => item.split(';')[0])
.forEach(c => agent.jar.setCookie(c));
长叹一口气
尽管我尽最大努力正确编写测试代码来验证设置块或之前的 describe/it 块中的请求代理,但我在后续 describe/it 块中从代理发出的任何请求都无法完成,因为 200 .
示例代码:
const request = require('supertest');
const server = require('../server');
let agent = request.agent(server);
let fakePerson = null;
beforeEach(async (done) => {
fakePerson = await Person.createMock();
agent.post(‘/login’)
.send({
email: ‘test@user.com’,
password: ‘password’
})
.end(function(err, res) {
if (err) throw err;
done();
});
});
describe('GET /users/:id', () => {
it ('renders user profile', () => {
return agent
.get(`/users/${fakePerson.id}`)
.expect(200)
});
});
我认为这可能与我在语法上形成异步调用的方式有关。但是在尝试使用 return
、.end()
语法在 beforeEach
块中返回登录调用的不同方式后,甚至 async/await,我已经确定(即放弃)代码必须正确组合。会不会是别的东西?
引用articles/resources:
- How to authenticate Supertest requests with Passport?
- https://medium.com/@juha.a.hytonen/testing-authenticated-requests-with-supertest-325ccf47c2bb
- https://gist.github.com/joaoneto/5152248
- https://medium.com/@bill_broughton/testing-with-authenticated-routes-in-express-6fa9c4c335ca
- https://github.com/visionmedia/supertest/issues/46
包版本:
- "koa": "^2.4.1"
- "koa-passport": "^4.0.1"
- "passport-json": "^1.2.0"
- "passport-local": "^1.0.0"
- "supertest": "^3.0.0"
- "jest": "^22.1.3"
我在测试运行期间花了一些时间逐步检查我的授权代码,但没有发现任何明显的问题。然后我有一个想法:如果请求本身格式不正确怎么办。事实证明我是对的!检查超测响应 header 中的 set-cookie
header 我看到:
[ 'koa:sess=eyJwYXNzcG9ydCI6eyJ1c2VyIjoxfSwiX2V4cGlyZSI6MTUyMTIyODg0NTU5OSwiX21heEFnZSI6ODY0MDAwMDB9; path=/; httponly,koa:sess.sig=EEZzgcg3bx8bm_FXRMobrr8_Yts; path=/; httponly' ]
作为单个字符串,这看起来有点可疑,这让我进行了更多谷歌搜索,我发现在为 Mocha 和 Jest 用户设置 cookie headers 的方式上存在差异作为全局Supertest 代理实例上的状态。请参阅:https://github.com/facebook/jest/issues/3547#issuecomment-302541653. Folks using Mocha had no trouble authenticating, while Jest users did. Turns out there is a bug Jest 全局变量导致 cookie 以单个字符串形式出现,而不是每个 cookie 的单独字符串数组——这是 Supertest 正确格式化请求所需要的。
这是一个基于问题中代码的变通方法,我们在其中正确地将有问题的 Jest 字符串解析为 Setup 块内 cookie/session 数据的作用域变量:
const request = require('supertest');
const server = require('../server');
let agent = request.agent(server);
let fakePerson = null;
let session = null;
beforeEach(async () => {
fakePerson = await Person.createMock();
agent.post(‘/login’)
.send({
email: fakePerson.email,
password: fakePerson.password’
})
.then(res => {
session = res
.headers['set-cookie'][0]
.split(',')
.map(item => item.split(';')[0])
.join(';')
expect(res.status).toEqual(200)
});
});
describe('GET /users/:id', () => {
it ('renders user profile', () => {
return agent
.get(`/users/${fakePerson.id}`)
.set('Cookie', session)
.expect(200)
});
});
我无法得到 internetross 的答案。经过大量调查,我终于找到了这个:https://github.com/facebook/jest/issues/3547#issuecomment-397183207.
我不得不更换
session = response.headers['set-cookie'][0]
.split(',')
.map(item => item.split(';')[0])
.join('; ')
和
response.headers['set-cookie'][0]
.split(',')
.map(item => item.split(';')[0])
.forEach(c => agent.jar.setCookie(c));
长叹一口气