Как заглушить зависимости в облачных функциях Firebase - PullRequest
0 голосов
/ 09 ноября 2019

Что я хотел бы сделать, так это провести модульное тестирование моих облачных функций в Firebase. Для этого я следую инструкциям, описанным в этом репо. Тестируемая функция выглядит следующим образом (я упростила ее):

validate_keypad_code.js

const functions = require('firebase-functions');

const { isRequestAuthorized } = require('../../services/authorization-service');
const { validateKeypadCode } = require('../../services/code-validation-service');
const { updateDeviceInputResource } = require('../../services/devices-gateway-service');
const { ERROR_MESSAGES, CUSTOM_HEADERS } = require('../../constants');

exports = module.exports = functions.https.onRequest((request, response) => {
    if(!isRequestAuthorized(request))
        return response.status(401).send(ERROR_MESSAGES.UNAUTHORIZED);

    return validateKeypadCode("myDevice", 223344).then(function(isvalid){
        if(isvalid)
            updateDeviceInputResource("account1", "myDevice", "resource1");

        return response.status(200).send();
    });
});

code_validation_service.js

async function validateKeypadCode(id, input) {
    // Makes some calls to services hosted on the internet
}

module.exports = {
    validateKeypadCode
};

device_gateway_service.js

function updateDeviceInputResource(id, devId, resId) {
    // Makes some calls to services hosted on the internet
}

module.exports = {
    updateDeviceInputResource
};
  1. Что я хочу проверить здесь:

    1. 401 возвращается, когда нет действительного заголовка авторизации
    2. Когда validateKeypadCode возвращает isValid = true => verify updateDeviceInputResource вызывается один раз
    3. Когда validateKeypadCode возвращает isValid = false => проверить updateDeviceInputResource не был вызван
    4. 200 ответ отправлен

Первый тест готов и яреализовал это так:

validate_keypad_code.spec.js

const chai = require('chai');
const assert = chai.assert;
const sinon = require('sinon');
const admin = require('firebase-admin');
const test = require('firebase-functions-test')();
const { ERROR_MESSAGES } = require('../../../../constants')

describe('Cloud functions', () => {
    let myFunctions;
    let authorizationHeaderValue = "798205486e954fa880a0b366e6725f71"

    before(() => {
      test.mockConfig({ authorization: { header: authorizationHeaderValue }});
      myFunctions = require('../../../../index');  
    });

    after(() => {
      test.cleanup();
    });

      it('should return a 401 unauthorized', (done) => {
        const req = { 
            body: {}, 
            get: () => '' 
        };

        const res = {
          status: (code) => {
            assert.equal(code, 401);
            return {
                send: (responseMessage) => {
                    assert.equal(responseMessage, ERROR_MESSAGES.UNAUTHORIZED);
                    done();
                }
            }
          }
        };

        myFunctions.validate_keypad_code(req, res);
      });
    });
  })

Теперь моя цель - заглушить служебные зависимости с помощью sinon и настроить моитесты:

it('should update device input resource when keypad code is valid', (done) => {
    // Mock validateKeypadCode and updateDeviceInputResource

    // Assert

    done();
});

Я пытался применить этот подход в комбинации судаление разрушения в моей облачной функции.

Заменено это:

// ...
const { validateKeypadCodeForMailbox } = require('../../services/code-validation-service');
const { updateDeviceInputResource } = require('../../services/devices-gateway-service');
// ...

exports = module.exports = functions.https.onRequest((request, response) => {
    // ...

    return validateKeypadCodeForMailbox(/* ... */).then(function(isvalid){
        if(isvalid)
            updateDeviceInputResource(/* ... */);
    // ...
});

на это:

// ...
const codeValidationService = require('../../services/code-validation-service');
const deviceGatewayService = require('../../services/devices-gateway-service');
// ...

exports = module.exports = functions.https.onRequest((request, response) => {
    // ...

    return codeValidationService.validateKeypadCodeForMailbox(/* ... */).then(function(isvalid){
        if(isvalid)
            deviceGatewayService.updateDeviceInputResource(/* ... */);
    // ...
});

И, затем, в моем тесте:

it('should update device input resource when keypad code is valid', (done) => {
        const validateKeypadCodeStub = sinon.stub();
        sinon.stub(codeValidationService, 'validateKeypadCode').callsFake(validateKeypadCodeStub);

        done();
      });

Я получаю следующую ошибку:

ReferenceError: codeValidationService не определен в Context.it (test / offline-unit-tests /...)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...