Subscribe to receive notifications of new posts:

Unit Testing Worker Functions

2019-03-15

2 min read

If you were not aware, Cloudflare Workers lets you run Javascript in all 165+ of our Data Centers. We’re delighted to see some of the creative applications of Workers. As the use cases grow in complexity, the need to smoke test your code also grows.  

More specifically, if your Worker includes a number of functions, it’s important to ensure each function does what it’s intended to do in addition to ensuring the output of the entire Worker returns as expected.

In this post, we’re going to demonstrate how to unit test Cloudflare Workers, and their individual functions, with Cloudworker, created by the Dollar Shave Club engineering team.

Dollar Shave Club is a Cloudflare customer, and they created Cloudworker, a mock for the Workers runtime, for testing purposes. We’re really grateful to them for this. They were kind enough to post on our blog about it.

This post will demonstrate how to abstract away Cloudworker, and test Workers with the same syntax you write them in.

Example Script

Before we get into configuring Cloudworker, let’s introduce the simple script we are going to test against in our example. As you can see this script contains two functions, both of which contribute to the response to the client.

addEventListener('fetch', event => {
 event.respondWith(handleRequest(event.request))
})

async function addition(a, b) {
  return a + b
}

async function handleRequest(request) {
  const added = await addition(1,3)
  return new Response(`The Sum is ${added}!`)
}

This script will be active for the route worker.example.com.

Directory Set Up

After I’ve created a new npm ( npm init ) project in a new directory, I placed my worker.js file inside, containing the above, and created the folder test which contains worker-test.js. The structure is laid out below.

.
----- worker.js
----- test
      . worker-test.js
----- node_modules
----- package.json
----- package-lock.json.

Next I need to install Cloudworker ( npm install @dollarshaveclub/cloudworker --save-dev ) and the Mocha testing framework ( npm install mocha --save-dev ) if you do not have it installed globally. Make sure that package.json reflects a value of mocha for tests, like:

"scripts": {
    "test": "mocha"
  }

Now we can finally write some tests! Luckily, mocha has async/await support which is going to make this very simple.  The idea is straightforward: Cloudworker allows you to place a Worker in development in front of an HTTP request and inspect the response.

Writing Tests!

Before any test logic, we’ll place two lines at the top of the test file ( worker-test.js ). The first line assigns all property values from Cloudworker and our Worker script to the global context before every async function() is run in mocha. The second line requires assert, which is commonly used to compare an expected output to a mocked output.

before(async function () {
   Object.assign(global, new (require('@dollarshaveclub/cloudworker'))(require('fs').readFileSync('worker.js', ‘utf8’)).context);
});

// You will replace worker.js with the relative path to your worker

const assert = require('assert')

Now, testing looks a lot more like a Worker itself as we access to all the underlying functions used by Cloudworker AND the Worker script.

describe('Worker Test', function() {

    it('returns a body that says The Sum is 4', async function () {
        let url = new URL('https://worker.example.com')
        let req = new Request(url)
        let res = await handleRequest(req)
        let body = await res.text()
        assert.equal(body, 'The Sum is 4!')
    })

    it('does addition properly', async function() {
        let res = await addition(1, 1)
        assert.equal(res, 2)
    })

})

We can test individual functions with our Worker this way, as shown above with the addition() function call. This is really powerful and allows for more confidence when deploying complex workers as you can test each component that makes up the script. We hope this was useful and welcome any feedback.

Cloudflare's connectivity cloud protects entire corporate networks, helps customers build Internet-scale applications efficiently, accelerates any website or Internet application, wards off DDoS attacks, keeps hackers at bay, and can help you on your journey to Zero Trust.

Visit 1.1.1.1 from any device to get started with our free app that makes your Internet faster and safer.

To learn more about our mission to help build a better Internet, start here. If you're looking for a new career direction, check out our open positions.
ServerlessCloudflare WorkersJavaScriptDeveloper PlatformDevelopers

Follow on X

Tim Obezuk|@obezuk
Cloudflare|@cloudflare

Related posts

October 31, 2024 1:00 PM

Moving Baselime from AWS to Cloudflare: simpler architecture, improved performance, over 80% lower cloud costs

Post-acquisition, we migrated Baselime from AWS to the Cloudflare Developer Platform and in the process, we improved query times, simplified data ingestion, and now handle far more events, all while cutting costs. Here’s how we built a modern, high-performing observability platform on Cloudflare’s network. ...