TL; DR - Jaki jest sposób testowania zasobów w węźle API (Express), który używa JWT do uwierzytelniania tylko z tokenem przyznano login/hasło logowania?Jak przetestować interfejs API węzła, który korzysta z uwierzytelniania JWT (z logowaniem użytkownika, aby uzyskać token)?
Jestem trochę nowy w testowaniu i chciałem uzyskać porady. Ostatecznym celem jest przetestowanie w pełni przetestowanego API, a następnie rozpoczęcie nauki tego, jak podłączyć go do rozwiązania Continuous Integration.
Technologie stosowane
- Pisałem API w Węzła wykorzystaniem Express,.
- Mongo to baza danych.
- Mongoose służy jako ODM.
- Pakiet jsonwebtoken służy do tworzenia/weryfikacji tokenów.
- Paszport służy do łatwego dodawania uwierzytelniania użytkownika jako oprogramowania pośredniego Express na trasach.
API Informacja
API ma różne zasoby - specyfika, które nie są istotne dla tego zapytania, ale pozwala tylko udawać, że to wszechobecne aplikacji Todo dla uproszczenia.
Każdy pojedynczy zasób zapisany w bazie danych jest powiązany z pojedynczym użytkownikiem.
Interfejs API wykorzystuje narzędzie JWT do uwierzytelniania na różnych punktach końcowych zasobów. Sam token zawiera unikalny identyfikator użytkownika, który jest przechowywany w zasobach w bazie danych Mongo. Aby uzyskać sam token, należy najpierw zarejestrować użytkownika (który zwraca token), a następnie zalogować się, aby uzyskać nowy token.
Przepisz kod.
mam zamiar uprościć poniższy kod i nie wykorzystuje żadnych configs namiotowe, itp ...
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);
mam pominięto niektóre przykładowy kod, aby utrzymać go w czystości i proste.
Na przykład użytkownika kontroler będzie zawierać modele i jego funkcje będzie:
- controller.create - zarejestruj dla nowych użytkowników (powraca tokena)
- controller.login - po potwierdzeniu przez nazwę użytkownika/hasło przez lokalny paszport zwrotny ważny token
- controller.getOne - w oparciu o wykorzystanie r ID pobrane z tokena JWT, zwróć dane użytkownika z Mongo za pomocą Mongoose.
- controller.update - Aktualizacja danych użytkownika w Mongo pomocą Mongoose
- controller.delete - Usuwanie danych użytkownika w Mongo użyciu Mongoose
kontrolerów Todo byłby zrobić coś podobnego - po prostu wchodząc w interakcje z danymi Mongo za pośrednictwem Mongoose, ale zapytania zawsze będą zawierać identyfikator użytkownika, aby powiązać określoną (na przykład) pozycję Todo z uwierzytelnionym użytkownikiem (uwierzytelnionym za pośrednictwem JWT).
Testowanie Conundrum
Jak bym go o coś takiego badania za pomocą kombinacji Mocha, Chai i SuperTest?
Would I:
- stworzyć bazę testową w Mongo i mieć ciąg połączenia się różnić w testach? Oznaczałoby to zapisanie rzeczywistych danych przechowywanych w bazie danych do testowania.
- Jakoś przetworzyć dane i nie używać w ogóle testowej bazy danych? Ale w jaki sposób jest zapisywane logowanie użytkownika/logowanie w celu odzyskania tokena?
W jaki sposób testy będą działać lokalnie podczas opracowywania w porównaniu do tego, kiedy wykonasz wdrożenie za pomocą jakiegoś narzędzia CI (coś, czego jeszcze nie zdążyłem się nawet nauczyć)?
Każda pomoc będzie mile widziane i mam nadzieję, że dałem wystarczająco dużo informacji z manekina danych/kodu powyżej.:/
Witam! Wymyśliłeś to? Próbuję też wdrożyć tego rodzaju testy. –