Шутка, возвращающая ложные срабатывания для функций Firebase?

#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)