问题描述
我正在测试创建项目 API。现在,为了创建一个项目,中间件将令牌检查到 cookie 中,以及数据库中是否存在会话。问题是,即使从第一次调用登录 API 开始创建会话(我可以在数据库中看到它),创建项 API 也无法“读取”会话。是不是 jest 发出了 2 个不同的请求(一个用于登录,另一个用于创建项目),或者会话不会持续到同一个请求中?
中间件看起来像这样:
exports.isAuth = (req,res,next) => {
if(!req.session.isAuth) {
return res.status(401).json({ message: 'You cannot take this action,please login' });
}
}
然后我的路线看起来像这样:
// isAuth.isAuth is the middleware that checks the session
router.put('/auth/api/sell',isAuth.isAuth,authController.createItem);
测试如下:
const supertest = require('supertest');
const request = supertest(app); // I exported app so that is not listening to any port at
// the time that I attach it to supertest
// I first have these 2 functions
function put(url,body) {
const httpRequest = request.put(url);
httpRequest.send(body);
httpRequest.set('Accept','application/json');
httpRequest.set('Origin',process.env.LOCALHOST_BE);
return httpRequest;
};
function post(url,body) {
const httpRequest = request.post(url);
httpRequest.send(body);
httpRequest.set('Accept',process.env.LOCALHOST_BE);
return httpRequest;
};
describe('create item',() => {
beforeEach(async (done) => {
// these lines are needed in order to mock the verify token function
const jwtSpy = jest.spyOn(jwt,'verify');
jwtSpy.mockReturnValue('some decoded token');
await post('/auth/api/login',{ email: 'test@test.com',password: '123456' });
done();
});
it('creates an item if all the inputs are correct',async (done) => {
try {
const reqItems = {
body: {
title: 'test',description: 'testing',image: 'https://res.cloudinary.com/dqhw3ma9u/image/upload/v1615827298/my-shop/before_after_analogy_rtkuec_vg8y7d.png',price: 10,stock: 1,}
};
const response = await put('/auth/api/sell',reqItems.body);
expect(response.body.message).toBe('item create');
done();
} catch (err) {
console.log(err);
done();
}
});
我尝试了以下方法但没有成功:
const request = require('super-request');
request(app)
.post('/auth/api/login')
.form({ email: 'test@test.com',password: '123456' }) // I also tried auth and send
.set('Accept','application/json')
.set('Origin',process.env.LOCALHOST_BE)
.end()
.put('/auth/api/sell')
.form(req.body) // I also tried auth and send
.set('Accept',process.env.LOCALHOST_BE)
.expect(200,"item create")
.end(function(err){
if(err){
throw err;
}
})
还有:
supertest.agent(app)
.post('/auth/api/login')
.send({ email: 'test@test.com',password: '123456' })
.expect(200)
.end(function (err,res) {
if(err) return done(err)
})
supertest.agent(app)
.put('/auth/api/sell')
.send(reqItems.body)
.expect(200)
.end(function (err,res) {
if(err) return done(err)
})
也在不同的文件 (loginFunctionTest) 中我有这个(我确信它不会解决问题,但我还是尝试了):
const superagent = require('superagent');
const agent = superagent.agent();
exports.login = function (request,done) {
request
.post('/auth/api/login')
.send({ email: 'test@test.com',password: '123456' })
.end(function (err,res) {
if(err) {
throw err;
}
agent.saveCookies(res);
done(agent);
});
};
然后在测试中我有这个(进入 beforeEach):
const login = require('./loginFunctionTest');
let agent;
login.login(request,function (loginAgent) {
agent = loginAgent;
done();
});
done();
我也试过:
global.req = jest.fn(() => Promise.resolve({ session: { isAuth: true } }));
还有:
const session = require('supertest-session');
const app = path to app
let testSession = null;
testSession = session(app);
let authenticatedSession;
testSession.post('/auth/api/login')
.send({ email: 'test@test.com',password: '123456' })
.expect(200)
.end(function (err) {
if(err) return done(err);
authenticatedSession = testSession;
return done();
})
authenticatedSession.put('/auth/api/sell') // here I get Cannot read property 'put' of undefined
.send(reqItems.body)
.expect(200)
.end(function (err,res) {
if(err) return done(err)
expect(res.body.message).toBe('created')
})
和(即使这样做没有任何意义,因为它与现在的测试相同):
request
.post('/auth/api/login')
.set('Accept',process.env.LOCALHOST_BE)
.send({ email: 'test@test.com',password: '123456' })
.then(() => {
request
.put('/auth/api/sell')
.set('Accept','application/json')
.set('Origin',process.env.LOCALHOST_BE)
.send(reqItems.body)
.expect(200,done)
})
解决方法
因此,为了解决这个问题,我做了以下操作(如果您按照文档进行操作很容易):
const expressRequestMock = require('express-request-mock');
const authController = require('../controllers/auth');
it('creates an item if all the inputs are correct',async (done) => {
try {
// these are the data that I need for my middleware to work
// you could have different data
const decorators = {
session: {
isAuth: true,user: {
_id: '602fb86391feb44b24d37c28',}
},body: {
title: 'test',description: 'testing',image: 'https://res.cloudinary.com/dqhw3ma9u/image/upload/v1615827298/my-shop/before_after_analogy_rtkuec_vg8y7d.png',price: 10,stock: 1,}
};
const { res } = await expressRequestMock(authController.createItem,decorators);
expect(res.statusCode).toBe(200); // I tried different inputs and it works with
// every codes,the message is not available though
done();
} catch (err) {
console.log(err);
done(err); // if u do only done() test will pass even though it should fail
}
});
可以找到模块文档here