Я пытаюсь провести модульное тестирование своего промежуточного ПО для аутентификации для Express. Промежуточное программное обеспечение довольно просто и может быть просмотрено ниже полностью:
const admin = require('./../config/firebase/firebase');
// Models - User
const User = require('./../models/user');
const auth = async (req, res, next) => {
try {
// The Authorization Bearer Token sent in the header of the request needs to be decoded.
const token = req.header('Authorization').replace('Bearer ', '');
const decoded = await admin.auth().verifyIdToken(token);
// Finding that user in the database by their Firebase UID.
const user = await User.findOne({ _id: decoded.uid });
// If that user does not exist, we'll throw an error.
if (!user) {
throw new Error();
}
// Making the user accessible to the endpoint.
req.user = user;
// Proceed
next();
} catch (e) {
// HTTP 404 Unauthorized Response Status
res.status(401).send({ error: 'Please authenticate.' });
}
}
module.exports = auth;
Поскольку Firebase Admin SDK возвращает объект, который содержит UID пользователя в качестве свойства, для целей моих тестов я создаю «поддельный токен», который является просто объектом со свойством UID. Затем я высмеиваю Admin SDK так, чтобы он возвращал все, что было передано, например:
module.exports = {
auth() {
return this;
},
verifyIdToken(token) {
return JSON.parse(token);
},
initializeApp(app) {
},
credential: {
cert() {
}
}
}
Поскольку промежуточное ПО auth ожидает найти пользователя в тестовой базе данных, я должен настроить его как Jest Setup в beforeAll
hook:
const userOneToken = JSON.stringify({ uid: 'example UID' });
const userOne = {
_id: 'example UID',
// ...
};
beforeAll(async () => {
await User.deleteMany();
await User.save(userOne);
app.use(auth).get('/', (req, res) => res.send());
});
Это означает, что промежуточное ПО всегда сможет получить взамен UID, который можно использовать для поиска тестового пользователя в тестовой базе данных.
Сам набор тестов после импорта моего приложения Express довольно прост, всего три теста:
const auth = require('./../../src/middleware/auth');
describe('Express Auth Middleware', () => {
test('Should return 401 with an invalid token', async () => {
await request(app)
.get('/')
.set('Authorization', 'Bearer 123')
.send()
.expect(401);
});
test('Should return 401 without an Authorization Header', async () => {
await request(app)
.get('/')
.send()
.expect(401);
});
test('Should return 200 with a valid token', async () => {
await request(app)
.get('/')
.set('Authorization', `Bearer ${userOneToken}`)
.send()
.expect(200);
});
});
Однако, похоже, что тесты имеют утечку памяти (очевидно, если вызвать с флагом --detectLeaks
). Кроме того, кажется, что Jest также находит открытую ручку, оставленную после последнего теста. Запуск пакета с флагом --detectOpenHandles
возвращает ошибку TCPSERVERWRAP
в запросе get
последнего теста.
Потенциальные решения были предложены в этом выпуске GitHub , но ни одно из них не помогло мне.
Любая помощь в решении этой проблемы будет принята с благодарностью, потому что все мои тестовые наборы теряют память, потому что они полагаются на Supertest. Спасибо.