首页 > 解决方案 > 开玩笑返回 Firebase 函数的误报?

问题描述

不得不为 Firebase 函数编写一些 Jest 测试,我遇到了一些麻烦。这是我正在尝试做的一个基本示例:

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返回一个被拒绝的承诺,这样我就可以获得正确的状态代码。

标签: javascriptfirebasejestjs

解决方案


onRequest是有承诺的,并期望回报它所做的整个工作的承诺。onRequest回调内部有一个悬空的承诺是一种反模式。

它应该是:

return auth.decodeToken(req)...

原始的 Promisethencatch内部都async导致了这个问题,因为async..await糖语法可以避免一些常见的 Promise 问题。如果将其写成,则可以避免上述问题以及嵌套承诺:

try {
  const decodedToken = await auth.decodeToken(req);
  ...
} catch (err) {
  ...
}

推荐阅读