我正在尝试使用passport
passport-jwt
和passport-local
为安全API提供用户身份验证,测试导致了一些问题。我正在尝试测试,当我使用授权标题集调用/meals
时会返回一份膳食列表。
目前在mocha中,当我尝试运行我的套件时,我得到Error: expected 200 "OK", got 401 "Unauthorized"
,我无法理解为什么。
以下代码段:
meals.test.js
// NPM imports
const request = require('supertest');
const expect = require('expect');
const {ObjectID} = require('mongodb');
// Local files
const app = require('./../app');
const {Meal} = require('./../models/meal');
const {meals, validUsers, populateUsers, populateMeals} = require('./seed/seed');
function createAuthenticatedRequest(loginDetails, done) {
let authenticatedRequest = request.agent(app);
authenticatedRequest
.post('/login')
.send(loginDetails)
.end(function (error, response) {
if (error) {
throw error;
}
done(authenticatedRequest)
});
}
beforeEach(populateMeals);
beforeEach(populateUsers);
describe('GET /meals', () => {
it('should get all the meals', (done) => {
createAuthenticatedRequest({email: validUsers[0].email, password: 'secret'}, function (request) {
console.log()
request
.get('/meals')
.expect(200)
.expect((res) => {
expect(res.body.length).toBe(2);
})
.end(done);
})
});
});
describe('POST /meals', () => {
it('should create a new meal', (done) => {
let mealName = 'Casserole';
let cookedWeight = 1000;
let servings = 5;
let portionSize = 200;
request(app)
.post('/meals')
.send({
mealName,
cookedWeight,
servings
})
.expect(200)
.expect((res) => {
expect(res.body.mealName).toBe(mealName);
expect(res.body.cookedWeight).toBe(cookedWeight);
expect(res.body.servings).toBe(servings);
expect(res.body.portionSize).toBe(portionSize);
})
.end((err) => {
if (err) {
return done(err);
}
Meal.find({mealName}).then((meals) => {
expect(meals.length).toBe(1);
expect(meals[0].mealName).toBe(mealName);
done();
}).catch((e) => done(e))
});
});
it('should not create a meal with incorrect data', (done) => {
let mealName = 'Casserole';
let cookedWeight = 'falafel';
let servings = 5;
request(app)
.post('/meals')
.send({
mealName,
cookedWeight,
servings
})
.expect(400, done);
});
it('should not create a meal with no data sent', (done) => {
request(app)
.post('/meals')
.send({})
.expect(400, done);
});
});
describe('GET /meals/:id', () => {
it('should return a specific meal', (done) => {
request(app)
.get(`/meals/${meals[0]._id.toHexString()}`)
.expect(200)
.expect((res) => {
expect(res.body.meal.mealName).toBe(meals[0].mealName);
})
.end(done);
});
it('should return a 404 if not found', (done) => {
request(app)
.get('/meals/asd')
.expect(404)
.end(done);
});
it('should return a 404 if doc not found', (done) => {
let hexId = new ObjectID().toHexString();
request(app)
.get(`/meals/${hexId}`)
.expect(404)
.end(done);
});
});
describe('DELETE /meals/:id', () => {
it('should delete a meal', (done) => {
let hexId = meals[0]._id.toHexString();
request(app)
.delete(`/meals/${meals[0]._id.toHexString()}`)
.expect(200)
.expect((res) => {
expect(res.body.meal._id).toBe(hexId);
})
.end((err) => {
if(err) {
return done(err)
}
Meal.findById(hexId).then((meal) => {
expect(meal).toNotExist();
done();
}).catch((e) => done(e));
})
});
it('should return a 404 if meal not found', (done) => {
let hexId = new ObjectID().toHexString();
request(app)
.delete(`/meals/${hexId}`)
.expect(404)
.end(done);
});
it('should return a 404 if malformed id is sent', (done) => {
request(app)
.delete('/meals/123abc')
.expect(404)
.end(done);
});
});
describe('PATCH /meals/:id', () => {
it('should update a meal if a valid request is sent', (done) => {
let id = meals[0]._id.toHexString();
let mealName = 'Testing update route';
request(app)
.patch(`/meals/${id}`)
.send({
mealName
})
.expect(200)
.expect((res) => {
expect(res.body.meal.mealName).toBe(mealName);
})
.end(done);
});
it('should return a 404 if meal is not found', (done) => {
let id = new ObjectID().toHexString();
let mealName = 'Testing update route';
request(app)
.patch(`/meals/${id}`)
.send({ mealName })
.expect(404)
.end(done);
});
it('should return a 404 if malformed id is sent', (done) => {
request(app)
.patch('/meals/123abc')
.expect(404)
.end(done);
});
});
路由/ meals.js
require('./../config/passport');
const express = require('express');
const router = express.Router();
const passport = require('passport');
const AuthenticationController =
require('./../controllers/authentication/authentication');
// Middleware to require login/auth
const requireAuth = passport.authenticate('jwt', { session: false });
const requireLogin = passport.authenticate('local', { session: false });
const {listMeals, getMeal, createMeal, updateMeal, deleteMeal} =
require('./../controllers/meals/meals');
router.get('/', requireAuth, listMeals);
router.post('/', createMeal);
router.get('/:id', getMeal);
router.delete('/:id', deleteMeal);
router.patch('/:id', updateMeal);
module.exports = router;
控制器/餐/ meals.js
const {ObjectID} = require('mongodb');
const _ = require('lodash');
const {Meal} = require('./../../models/meal');
let listMeals = (req, res) => {
console.log(req.headers);
Meal.find({
}).then((meals) => {
res.send(meals)
}, (e) => {
res.status(400).send(e);
});
};
let getMeal = (req, res) => {
let id = req.params.id;
if(!ObjectID.isValid(id)) {
return res.sendStatus(404);
}
Meal.findOne({
_id : id
}).then((meal) => {
if(!meal) {
return res.sendStatus(404);
}
res.status(200).send({meal})
}, () => {
res.status(404).send();
});
};
let createMeal = (req, res) => {
let meal = new Meal({
mealName : req.body.mealName,
cookedWeight : req.body.cookedWeight,
servings : req.body.servings,
portionSize: req.body.cookedWeight / req.body.servings
});
meal.save().then((doc) => {
res.send(doc)
}, (e) => {
res.status(400).send(e);
});
};
let deleteMeal = (req, res) => {
let id = req.params.id;
if(!ObjectID.isValid(id)) {
return res.sendStatus(404);
}
Meal.findOneAndRemove({
_id : id
}).then((meal) => {
if(!meal) {
return res.sendStatus(404);
}
res.status(200).send({meal});
}).catch((e) => {
res.sendStatus(400).send(e);
});
};
let updateMeal = (req, res) => {
let id = req.params.id;
let body = _.pick(req.body, ['mealName', 'servings', 'cookedWeight']);
if(!ObjectID.isValid(id)) {
return res.sendStatus(404);
}
Meal.findOneAndUpdate({
_id : id
}, { $set : body}, {new : true}).then((meal) => {
if(!meal) {
return res.sendStatus(404);
}
res.status(200).send({meal});
}).catch((e) => {
res.status(400).send(e);
})
};
module.exports = {
createMeal,
listMeals,
getMeal,
deleteMeal,
updateMeal
};
如果需要更多信息,请告诉我
答案 0 :(得分:1)
因此经过两天的戳戳和刺激后,我找到了一个解决方案,在此发布以供将来参考,创建了以下函数来创建Authorization标头并将其返回以供请求使用。
// Auxiliary function.
function createLoginToken(server, loginDetails, done) {
request(server)
.post('/login')
.send(loginDetails)
.end(function(error, response) {
if (error) {
throw error;
}
let loginToken = response.body.token;
done(loginToken);
});
}
然后如下调用:
it('should get all the meals', (done) => {
createLoginToken(app, { email: validUsers[0].email, password: 'secret'}, function(header) {
request(app)
.get('/meals')
.set('Authorization', header)
.expect(200)
.expect((res) => {
expect(res.body.length).toBe(2);
})
.end(done);
});
});
非常感谢Juha Hytönen他的博客文章指出了我正确的方向