How do you unit test execute a firebase function with an expression?

With Firebase features, you can use Express to achieve good functionality, such as middleware, etc. I used this example to get an idea of ​​how to write Expressbased HTTPS Firebase functions.

However, my problem is that the official Firebase documentation on how to do unit testing does not include the https-express example.

So my question is how to do unit testing of the following function (typing):

// omitted init. of functions
import * as express from 'express';

const cors = require('cors')({origin: true});
const app = express();
app.use(cors);

// The function to test
app.get('helloWorld, (req, res) => {
   res.send('hello world');
   return 'success';
});

exports.app = functions.https.onRequest(app);
+9
source share
7

supertest Firebase. , /, mocha.

import * as admin from 'firebase-admin'
import * as testFn from 'firebase-functions-test'
import * as sinon from 'sinon'
import * as request from 'supertest'
const test = testFn()
import * as myFunctions from './get-tested' // relative path to functions code
const adminInitStub = sinon.stub(admin, 'initializeApp')

request(myFunctions.app)
  .get('/helloWorld')
  .expect('hello world')
  .expect(200)
  .end((err, res) => {
    if (err) {
      throw err
    }
  })
+1
0

, , app.get("helloWorld",...) .

:

main.js:

// in the Firebase code:
export function helloWorld(req, res) { res.send(200); }
app.get('helloWorld', helloWorld);

main.spec.js:

// in the test:
import { helloWorld } from './main.js';
import sinon from 'sinon';
const reqMock = {};
const resMock = { send: sinon.spy() }; 

it('always responds with 200', (done) => {
    helloWorld(reqMock, resMock);
    expect(resMock.send.callCount).toBe(1);
    expect(resMock.send).toHaveBeenCalledWith(200);
});
0

- .

FireBase. . , , , Express. , , , Express, - . , "" .

Express , , , .

, , .

0

, firebase-functions-test node-mocks-http.

FunctionCaller.js:

'use strict';

var httpMocks       = require('node-mocks-http');
var eventEmitter    = require('events').EventEmitter;

const FunctionCaller = class {

  constructor(aYourFunctionsIndex) {
    this.functions_index = aYourFunctionsIndex;
  }

  async postFunction(aFunctionName,aBody,aHeaders,aCookies) {

    let url = (aFunctionName[0]=='/') ? aFunctionName : '/${aFunctionName}';
    let options = {
      method: 'POST',
      url: url,
      body: aBody
    };
    if (aHeaders)
      options.headers = aHeaders;

    if (aCookies) {
      options.cookies = {};
      for (let k in aCookies) {
        let v = aCookies[k];
        if (typeof(v)=='string') {
          options.cookies[k] = {value: v};
        } else if (typeof(v)=='object') {
          options.cookies[k] = v;
        }
      }
    }

    var request = httpMocks.createRequest(options);
    var response = httpMocks.createResponse({eventEmitter: eventEmitter});


    var me = this;
    await new Promise(function(resolve){
      response.on('end', resolve);
      if (me.functions_index[aFunctionName])
        me.functions_index[aFunctionName](request, response);
      else
        me.functions_index.app(request, response);
    });
    return response;
  }

  async postObject(aFunctionName,aBody,aHeaders,aCookies) {
    let response = await this.postFunction(aFunctionName,aBody,aHeaders,aCookies);
    return JSON.parse(response._getData());
  }

  async getFunction(aFunctionName,aParams,aHeaders,aCookies) {
    let url = (aFunctionName[0]=='/') ? aFunctionName : '/${aFunctionName}';
    let options = {
      method: 'GET',
      url: url,
      query: aParams   // guessing here
    };
    if (aHeaders)
      options.headers = aHeaders;

    if (aCookies) {
      options.cookies = {};
      for (let k in aCookies) {
        let v = aCookies[k];
        if (typeof(v)=='string') {
          options.cookies[k] = {value: v};
        } else if (typeof(v)=='object') {
          options.cookies[k] = v;
        }
      }
    }

    var request = httpMocks.createRequest(options);
    var response = httpMocks.createResponse({eventEmitter: eventEmitter});

    var me = this;
    await new Promise(function(resolve){
      response.on('end', resolve);
      if (me.functions_index[aFunctionName])
        me.functions_index[aFunctionName](request, response);
      else
        me.functions_index.app(request, response);
    });
    return response;
  }

  async getObject(aFunctionName,aParams,aHeaders,aCookies) {
    let response = await this.getFunction(aFunctionName,aParams,aHeaders,aCookies);
    return JSON.parse(response._getData());
  }

};

module.exports = FunctionCaller;

:

exports.app = functions.https.onRequest(expressApp);

firebase.json :

"rewrites": [
  :
  :
  :
  {
    "source": "/path/to/function", "function": "app"
  }
]

:

const FunctionCaller = require('../FunctionCaller');
let fire_functions = require('../index');
const fnCaller = new FunctionCaller(fire_functions);

:

let response = await fnCaller.postFunction('/path/to/function',anObject);

anObject request.body .

8 Firebase, / ..

0

import supertest from 'supertest'
import test from 'firebase-functions-test'
import sinon from 'sinon'
import admin from 'firebase-admin'

let undertest, adminInitStub, request
const functionsTest = test()

beforeAll(() => {
  adminInitStub = sinon.stub(admin, 'initializeApp')
  undertest = require('../index')
  // inject with the exports.app methode from the index.js
  request = supertest(undertest.app)
})

afterAll(() => {
  adminInitStub.restore()
  functionsTest.cleanup()
})

it('get app', async () => {
  let actual = await request.get('/')
  let { ok, status, body } = actual
  expect(ok).toBe(true)
  expect(status).toBeGreaterThanOrEqual(200)
  expect(body).toBeDefined()
})
0

postman unit test. URL-

https://us-central1-your-project.cloudfunctions.net/hello

app.get('/hello/',(req, res) => {
   res.send('hello world');
   return 'success';
});
-2

Source: https://habr.com/ru/post/1695029/


All Articles