Offline unit testing Google Cloud Functions in Typescript

The problem

Google’s documentation on Firebase is primarily in JavaScript, but we want to use TypeScript. That means we lose a lot of the freedom that node.js provides (not really a bad thing, though, as that freedom lets us create absolutely unmaintainable code)

So what do we need to do?

The obvious answer is mocking, but there are some barriers before we can get there. Primarily, jest itself doesn’t handle compiling typescript.

Overview:

  1. Need the deps, jest, babel, ts-node, firebase-functions-test
  2. Set up the configuration to handle typescript
  3. Write test code

So, get the dependencies…

        "babel-jest": "^24.9.0",
        "firebase-functions-test": "^0.1.6",
        "jest": "^24.9.0",
        "ts-jest": "^24.1.0",
        "ts-node": "^8.4.1",

Why babel? That’s what will end up handling typescript type checking for us. This piece really confused me at first.

Create the babel.config.js

module.exports = {
    presets: [
        ['@babel/preset-env', {targets: {node: 'current'}}],
        '@babel/preset-typescript',
    ],
};

Create the jest.config.js

module.exports = {
  preset: 'ts-jest',
  testEnvironment: 'node',
};

Now, in your unit test

import functions from 'firebase-functions-test';

...

let profile: Profile = {...your data here...};

...

mockQueryResponse.mockResolvedValue(
    {
        data: () => {
            return profile
        }
    }
);

...

jest.mock('firebase-admin', () => ({
    initializeApp: jest.fn(),
    firestore: () => ({
        collection: jest.fn(path => ({
            doc: jest.fn(path => ({
                get: mockQueryResponse,
                update: mockQueryResponse
            }))
        }))
    })
}));
...
test('create a subscription', async () => {
    functions();
    ... service logic, assertions, etc.
});

If it looks confusing, well it was. 😂

References

This post here helped complete the puzzle for me