#javascript #firebase #jestjs
# #javascript #firebase #jestjs
Вопрос:
Необходимо написать несколько тестов Jest для функций Firebase, и у меня возникают небольшие проблемы. Вот простой пример того, что я пытаюсь сделать:
databaseUtils.js
function funcOne() {
return Promise.resolve();
}
function funcTwo() {
return Promise.resolve();
}
index.js
exports.myTest = functions.https.onRequest(async (req, res) => {
try {
await databaseUtils.funcOne();
await databaseUtils.funcTwo();
return res.status(200);
} catch (error) {
console.log(error);
return res.status(403);
}
});
index.test.js
describe('myTest', () => {
it('test 1', async () => {
const req = {}
const res = {
status: jest.fn()
};
await functions.myTest(req, res);
expect(res.status).toHaveBeenCalledWith(200)
});
it('test 2', async () => {
const req = {}
const res = {
status: code => {
expect(code).toBe(403);
}
};
await functions.myTest(req, res);
});
it('test 3', (done) => {
const req = {}
const res = {
status: code => {
expect(code).toBe(403);
done();
}
};
functions.myTest(req, res);
});
})
Когда я запускаю свои тесты, тест 1 завершается с ошибкой, в то время как тесты 2 и 3 проходят, но с неправильными значениями:
JestAssertionError: expect(received).toBe(expected) // Object.is equality
Expected: 403
Received: 200
matcherResult: {
actual: 200,
expected: 403,
message: [Function],
name: 'toBe',
pass: false
}
Бегал по кругу, пытаясь заставить это работать должным образом, но я не могу понять, что я делаю не так?
Как только я это выясню, я бы тогда смоделировал funcOne
/ funcTwo
, чтобы вернуть отклоненное обещание, чтобы я мог получить правильный код состояния.
Ответ №1:
onRequest
осознает обещания и, как ожидается, вернет обещание всей выполняемой им работы. То, что внутри обратного вызова есть оборванное обещание onRequest
, является антипаттером.
Это должно быть:
return auth.decodeToken(req)...
То then
, что внутри и внутри есть необработанные обещания catch
async
, усугубляет проблему, потому async..await
что это синтаксис сахара, который позволяет избежать нескольких распространенных проблем с обещаниями. Указанной проблемы, а также вложенных обещаний можно было бы избежать, если бы это было записано как:
try {
const decodedToken = await auth.decodeToken(req);
...
} catch (err) {
...
}
Комментарии:
1. Спасибо, что заметили это и прояснили! Я переписал фиктивный тест и обновил исходное сообщение с его помощью, используя try / catch, и я все еще получаю те же результаты.
2. Это true positive, потому что вы ничего не сделали для сбоя функции. Макет модулей, которые ответственны за сбой, поскольку функции databaseUtils используются в качестве методов, их можно высмеивать без jest.mock, что-то вроде
jest.spyOn(databaseUtils, 'funcOne').mockRejectedValue('foo'); ... expect(res.status).toHaveBeenCalledWith(403)