Chai-http:无法设置节点值 ctx.state
Chai-http: cannot set value of nodes ctx.state
我正在使用 NodeJS 和 KOA 创建一个 API。为了进行测试,我使用了 chai (chai-http) 和 mocha。
当我在我的控制器中使用 const { username } = ctx.state.user
来获取发送请求的用户的用户名时,问题就出现了。当使用我的应用程序(使用 Flutter)或使用 Postman 访问它们时,它可以工作,但是当 运行 使用 mocha 进行测试时,我得到错误 TypeError: Cannot destructure property 'username' of 'undefined' or 'null'
。在调试代码时,我发现 ctx
有一个 state
的键,但该键的值为空。我尝试了 .set(...)
和 .send(...)
方法,但它们只修改了 ctx.request.header
和 ctx.request.body
.
中的值
所以我的问题是:是否可以使用 chai 为 ctx.state
设置一个值,如果可以,如何设置?我想输入类似 {user: {username: 'chai'}}
.
的内容
下面是2个主要部分,要测试的控制器部分和测试方法:
async function bar(ctx, next) {
const { username } = ctx.state.user;
const { value } = ctx.request.body;
// do something with value and username
ctx.status = 200;
}
it("With correct gameKey: should return the rating of the game", done => {
chai
.request('http://localhost:3000')
.post('/foo/bar')
.set('content-type', 'application/json')
.send({value: 3});
.end((err, res) => {
// do some tests
done();
});
});
这是来自服务器索引和测试文件的完整代码:
const Koa = require('koa');
const Jwt = require('koa-jwt');
const Router = require('koa-router');
const Cors = require('@koa/cors');
const BodyParser = require('koa-bodyparser');
const Helmet = require('koa-helmet');
const app = new Koa();
const router = new Router();
router.post('/foo/bar', bar);
async function bar(ctx, next) {
const { username } = ctx.state.user;
const { value } = ctx.request.body;
// do something with value and username
ctx.status = 200;
}
app.use(Helmet());
app.use(Cors());
app.use(BodyParser({
enableTypes: ['json'],
strict: true,
onerror(err, ctx) {
ctx.throw('Request body could not be parsed', 422);
},
}));
app.use(Jwt({ secret: process.env.SECRET }).unless({
path: [
// Whitelist routes that don't require authentication
/^\/auth/,
],
}));
app.use(router.routes());
app.use(router.allowedMethods());
app.listen(3000, () => console.log(`API server started on localhost:3000`));
const chai = require("chai");
const chaiHttp = require("chai-http");
chai.use(chaiHttp);
const expect = require('chai').expect;
const userCredentials = {
username: 'chai',
password: 'chai'
}
describe("Route: games/", () => {
before(() => {
chai
.request('http://localhost:3000')
.post('/auth')
.set('content-type', 'application/json')
.send(userCredentials)
.end((err, res) => {
expect(res.status).to.be.eql(200);
});
});
describe("Sub-route: GET /", () => {
describe("Sub-route: PUT /:gameKey/rating", () => {
it("With correct gameKey: should return the rating of the game", done => {
chai
.request('http://localhost:3000')
.post('/foo/bar')
.set('content-type', 'application/json')
.send({value: 3});
.end((err, res) => {
expect(res.status).to.be.eql(200);
done();
});
});
});
});
});
根据 KOA 文档ctx.state
推荐的命名空间,用于通过中间件和前端视图传递信息。
app.use(function * (next) {
var ctx = this
ctx.request
ctx.response
ctx.body = 'hello'
ctx.state.user = yield User.find(id).fetch()
next()
}
所以我认为你可以在中间件函数中设置 ctx.state
,你可以在下一个请求处理程序中使用它。
感谢 的评论,我明白了。我不得不使用中间件,所以我在 before()
方法中保存了随请求检索到的令牌,并使用 .set("Authorization", "Bearer " + token)
.
将其添加到其他请求中
工作测试如下所示:
const chai = require("chai");
const chaiHttp = require("chai-http");
chai.use(chaiHttp);
const expect = require('chai').expect;
const userCredentials = {
username: 'chai',
password: 'chai'
}
describe("Route: games/", () => {
var token;
before(() => {
chai
.request('http://localhost:3000')
.post('/auth')
.set('content-type', 'application/json')
.send(userCredentials)
.end((err, res) => {
expect(res.status).to.be.eql(200);
token = res.body.token; // Added this
});
});
describe("Sub-route: GET /", () => {
describe("Sub-route: PUT /:gameKey/rating", () => {
it("With correct gameKey: should return the rating of the game", done => {
chai
.request('http://localhost:3000')
.post('/foo/bar')
.set("Authorization", "Bearer " + token) // Added this
.set('content-type', 'application/json')
.send({value: 3});
.end((err, res) => {
expect(res.status).to.be.eql(200);
done();
});
});
});
});
});
我正在使用 NodeJS 和 KOA 创建一个 API。为了进行测试,我使用了 chai (chai-http) 和 mocha。
当我在我的控制器中使用 const { username } = ctx.state.user
来获取发送请求的用户的用户名时,问题就出现了。当使用我的应用程序(使用 Flutter)或使用 Postman 访问它们时,它可以工作,但是当 运行 使用 mocha 进行测试时,我得到错误 TypeError: Cannot destructure property 'username' of 'undefined' or 'null'
。在调试代码时,我发现 ctx
有一个 state
的键,但该键的值为空。我尝试了 .set(...)
和 .send(...)
方法,但它们只修改了 ctx.request.header
和 ctx.request.body
.
所以我的问题是:是否可以使用 chai 为 ctx.state
设置一个值,如果可以,如何设置?我想输入类似 {user: {username: 'chai'}}
.
下面是2个主要部分,要测试的控制器部分和测试方法:
async function bar(ctx, next) {
const { username } = ctx.state.user;
const { value } = ctx.request.body;
// do something with value and username
ctx.status = 200;
}
it("With correct gameKey: should return the rating of the game", done => {
chai
.request('http://localhost:3000')
.post('/foo/bar')
.set('content-type', 'application/json')
.send({value: 3});
.end((err, res) => {
// do some tests
done();
});
});
这是来自服务器索引和测试文件的完整代码:
const Koa = require('koa');
const Jwt = require('koa-jwt');
const Router = require('koa-router');
const Cors = require('@koa/cors');
const BodyParser = require('koa-bodyparser');
const Helmet = require('koa-helmet');
const app = new Koa();
const router = new Router();
router.post('/foo/bar', bar);
async function bar(ctx, next) {
const { username } = ctx.state.user;
const { value } = ctx.request.body;
// do something with value and username
ctx.status = 200;
}
app.use(Helmet());
app.use(Cors());
app.use(BodyParser({
enableTypes: ['json'],
strict: true,
onerror(err, ctx) {
ctx.throw('Request body could not be parsed', 422);
},
}));
app.use(Jwt({ secret: process.env.SECRET }).unless({
path: [
// Whitelist routes that don't require authentication
/^\/auth/,
],
}));
app.use(router.routes());
app.use(router.allowedMethods());
app.listen(3000, () => console.log(`API server started on localhost:3000`));
const chai = require("chai");
const chaiHttp = require("chai-http");
chai.use(chaiHttp);
const expect = require('chai').expect;
const userCredentials = {
username: 'chai',
password: 'chai'
}
describe("Route: games/", () => {
before(() => {
chai
.request('http://localhost:3000')
.post('/auth')
.set('content-type', 'application/json')
.send(userCredentials)
.end((err, res) => {
expect(res.status).to.be.eql(200);
});
});
describe("Sub-route: GET /", () => {
describe("Sub-route: PUT /:gameKey/rating", () => {
it("With correct gameKey: should return the rating of the game", done => {
chai
.request('http://localhost:3000')
.post('/foo/bar')
.set('content-type', 'application/json')
.send({value: 3});
.end((err, res) => {
expect(res.status).to.be.eql(200);
done();
});
});
});
});
});
根据 KOA 文档ctx.state
推荐的命名空间,用于通过中间件和前端视图传递信息。
app.use(function * (next) {
var ctx = this
ctx.request
ctx.response
ctx.body = 'hello'
ctx.state.user = yield User.find(id).fetch()
next()
}
所以我认为你可以在中间件函数中设置 ctx.state
,你可以在下一个请求处理程序中使用它。
感谢 before()
方法中保存了随请求检索到的令牌,并使用 .set("Authorization", "Bearer " + token)
.
工作测试如下所示:
const chai = require("chai");
const chaiHttp = require("chai-http");
chai.use(chaiHttp);
const expect = require('chai').expect;
const userCredentials = {
username: 'chai',
password: 'chai'
}
describe("Route: games/", () => {
var token;
before(() => {
chai
.request('http://localhost:3000')
.post('/auth')
.set('content-type', 'application/json')
.send(userCredentials)
.end((err, res) => {
expect(res.status).to.be.eql(200);
token = res.body.token; // Added this
});
});
describe("Sub-route: GET /", () => {
describe("Sub-route: PUT /:gameKey/rating", () => {
it("With correct gameKey: should return the rating of the game", done => {
chai
.request('http://localhost:3000')
.post('/foo/bar')
.set("Authorization", "Bearer " + token) // Added this
.set('content-type', 'application/json')
.send({value: 3});
.end((err, res) => {
expect(res.status).to.be.eql(200);
done();
});
});
});
});
});