TL; DR - Каков способ тестирования ресурсов в API-интерфейсе (Express), который использует JWT для аутентификации только с самим токеном предоставляется имя пользователя/пароль?Как протестировать API-интерфейс узла, который использует аутентификацию JWT (с именем пользователя для получения токена)
Я новичок в тестировании и хотел получить совет. Конечная цель состоит в том, чтобы иметь полностью протестированный API, а затем начать изучать, как подключиться к решению непрерывной интеграции.
технологии в использовании
- Я написал API в Node с использованием Экспресс.
- Mongo - это база данных.
- Mongoose используется как ODM.
- jsonwebtoken package используется для создания и проверки токенов.
- Паспорт используется, чтобы легко добавлять аутентификацию пользователя в качестве промежуточного программного обеспечения Express на маршрутах.
API Информация
API-интерфейс имеет различные ресурсы - специфика которых не важны для этого запроса, но давайте просто делать вид, что вездесущий Todo приложение для простоты.
Каждый отдельный ресурс, сохраненный в базе данных, связан с одним пользователем.
API использует JWT для аутентификации на разных конечных точках ресурса. Сам токен содержит уникальный идентификатор пользователя, который хранится в ресурсе в базе данных Mongo. Для получения самого токена требуется, чтобы пользователь сначала зарегистрировался (который возвращает токен), а затем авторизуется, чтобы получить новый токен.
Притворись, что код.
Я собираюсь упростить код, приведенный ниже, и не использовать любые среды конфиги и т.д ...
app.js
var express = require('express');
var app = express();
var mongoose = require('mongoose');
var bodyParser = require('body-parser');
var passport = require('passport');
mongoose.connect('mongodb://localhost/somedatabasename');
app.set('port', process.env.PORT || 3000);
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());
app.use(passport.initialize());
// ... Passport JWT Strategy goes here - omitted for simplicity ...
var userRouter = require('./api/users/routes');
app.use('/users', userRouter);
var todoRouter = require('./api/todos/routes');
app.use('/todos', todoRouter);
app.listen(app.get('port'), function() {
console.log('App now running on http://localhost:' + app.get('port'));
});
./api/todos/routes.js
var router = require('express').Router();
var controller = require('./controller');
var passport = require('passport');
router.route('/')
.all(passport.authenticate('jwt', { session: false}))
.get(controller.getAll)
.post(controller.create);
router.route('/:id')
.all(passport.authenticate('jwt', { session: false}))
.get(controller.getOne)
.put(controller.update)
.delete(controller.delete);
module.exports = router;
./api/users/routes.js
var router = require('express').Router();
var controller = require('./controller');
var passport = require('passport');
router.route('/')
// User signup
.post(controller.create);
router.route('/me')
// User Login
.post(passport.authenticate('local', { session: false}), controller.login)
// Get current user's data
.get(passport.authenticate('jwt', { session: false}), controller.getOne)
// Update current user's data
.put(passport.authenticate('jwt', { session: false}), controller.update)
// Delete current user
.delete(passport.authenticate('jwt', { session: false}), controller.delete);
module.exports = router;
./api/users/model.js
var mongoose = require('mongoose');
var bcrypt = require('bcrypt');
var UserSchema = new mongoose.Schema({
username: {
type: String,
required: true,
unique: true
},
password: {
type: String,
required: true
}
});
// ... for simplicity imagine methods here to
// - hash passwords on a pre save hook using bcrypt
// - compare passwords using bcrypt when logging in
module.exports = mongoose.model('User', UserSchema);
./api/todos/model.js
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var momentSchema = new Schema({
title: {
type: String
},
// Bunch of other fields here...
_user: {
type: Schema.Types.ObjectId,
ref: 'User'
}
});
module.exports = mongoose.model('Moment', momentSchema);
я опустил некоторые из примеров кода, чтобы держать его в чистоте и простой.
Например, контроллер в пользователя будет включать в себя модели и ее функции будут:
- controller.create - Регистрация для новых пользователей (возвращает маркер)
- controller.login - после согласования имени пользователя и пароля, подтвержденного Passport Local, затем верните действительный токен
- controller.getOne - на основе использования r ID, извлеченный из токена JWT, возвращает данные пользователя из Mongo, используя Mongoose.
- controller.update - Обновление данных пользователя в Монго, используя Mongoose
- controller.delete - Удалить данные пользователя в Монго, используя Mongoose
Контроллеры Todo был бы сделать что-то подобное - просто взаимодействуя с данными Mongo через Mongoose, но запросы всегда будут включать идентификатор пользователя, чтобы связать конкретный (например) элемент Todo с аутентифицированным пользователем (аутентифицированный через JWT).
Тестирование Conundrum
Как бы идти о тестировании что-то вроде этого, используя комбинацию Мокко, Chai и Supertest?
ли я:
- создать тестовую базу данных в Монго и есть строка подключения будет отличаться в тестах? Это будет означать сохранение фактических данных, хранящихся в базе данных для тестирования.
- Выкачать данные как-то и не использовать тестовую базу данных вообще? Но тогда как пользователь сохраняет/регистрируется, чтобы получить токен?
Как тестирование будет выполняться локально при разработке или при развертывании с использованием какого-либо инструмента CI (чего я еще не получил в своих исследованиях)?
Любая помощь будет высоко ценится, и я надеюсь, что я дал достаточно информации с фиктивными данными/код выше:./
Привет! Вы поняли это? Я также пытаюсь реализовать такие тесты. –