2016-05-17 4 views
12

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 (чего я еще не получил в своих исследованиях)?

Любая помощь будет высоко ценится, и я надеюсь, что я дал достаточно информации с фиктивными данными/код выше:./

+0

Привет! Вы поняли это? Я также пытаюсь реализовать такие тесты. –

ответ

1

Во время тестирования вы обычно издеваются свой Монго DB (что-то вроде mongo-mock Таким образом, вам не нужна фактическая база данных, запускающая ваши тесты (вы не тестируете базу данных, но ваш код).

Во время тестирования вы замените mongodb на mongo-mock, а затем запустите свой тест. Чтобы получить свой токен, вам нужно будет отправить сообщение на ваш URL-адрес /me с действительными издеваемыми учетными данными, эта конечная точка вернет токен, который вы затем будете использовать при следующем вызове для проверки вашей другой конечной точки.

На торцевой стороне вещей я обычно проверяю его в начале запроса перед входом в другие конечные точки.(Я не использовал паспорт, но идея):

app.use(validate_jwt_middleware); 
app.use('/users', userRouter); 

Таким образом, если маркер является недействительным, это не подходит для всего сайта, а не только ваш раздел.

Кроме того, я не использую SuperTest, но chai-http, поэтому я не могу помочь вам с вашей спецификой.

Надеюсь, что это поможет,

Смежные вопросы