December 14, 2020
Ever started a new project quickly realizing you would love to re-use some code from another project? This happened to me during the development of functional tests for Google Cloud functions. Maybe it can be of help to you too.
Unreadable code can feel like untying your earplug wires after getting them out of your pocket. Take a look at how a test might've looked for a cloud function (feel free to skip it, I'm just trying to show this is a callback mess):
it("should work", () => {
let statusCode = 200;
let responseBody = "";
const stubbedResponse = {
status: code => {
statusCode = code;
},
send: body => {
expect(statusCode).to.equal(201);
expect(body).to.equal("Hello World");
},
};
yourFunction({}, stubbedResponse);
});
Don't even start about if your function runs async 🤢 (which most do). Promise + callback hell it'll be for you.
With some abstraction magic, this test became much more simple:
const asyncFunction = promisifyHandler(yourFunction);
it("should work", async () => {
const { status, body } = await asyncFunction({});
expect(statusCode).to.equal(201);
expect(body).to.equal("Hello World");
});
Let yourFunction
go wild! It can .send
, .write
, .end
and much more!
I've created a little npm package out of this; for you (and myself) to re-use! The Google Cloud Function handlers are actually just Express handlers. Did you know this is the same in Firebase Functions? So to test Firebase Functions locally works with this too!
npm install pify-express-handler --save-dev
Let me know your thoughts! I hope it helps you out :).
If you're using Serverless Framework you might be better off using their testing infrastructure. But don't use it for just testing, it's very heavy.
Another option is using firebase-functions-test
if you're using firebase. But, you still need to stub your own res
object and do require
s in funky locations. You can see an example test at work in their repo.