Isolating production code in Javascript
15 September, 2017 2 min read

While writing services, we are likely to come around pieces of code that should only run in production. For eg. A function that takes a list of email addresses and sends out promotional emails, or a function that makes a financial transaction. You want those function to run only while on production. You don’t want to accidentally send out emails while testing your code.

A simple way to solve this is to check if an environment variable is set to production on each of this kind of functions.

const sendEmail = email => {
  // We don't want to be sending out emails while developing or testing.
  if (process.env.NODE_ENV !== 'production') return
  // Code to send email
}

export default sendMail

But this is probably not the best way we can solve this. There are many issues we face if we go down this path.

  1. You can’t test those functions as they are only ever going to run on production. Well, you can, by changing process.env while testing and restoring it back. But it has its own side-effects. If you have tests running in async and you change process.env to test a function after mocking it, Some other tests might be running at the same time that hasn’t done mocking and expected the environment variable to be tested so that the code doesn’t run. NOT GOOD!.
  2. If you have such functions that call other such functions, you have to mock all those functions even if you want to test one of them.

We need a better way to solve this. We should be able to specify that a function is isolated and should only run when in production. And we still need the ability to ask it run while testing without messing with global variables. And only the function we asked to run, should be the one that runs. Other should still stay isolated, even if they are called from the function that we asked to run.

To solve this, I created Isograte. You can use it to isolate a function and then easily integrate it back while testing. Isograte exposes two functions, isolate and integrate. You can isolate any function to run only in production and integrate it back while testing. Only the function you directly called integrate on gets run.

import { isolate } from 'isograte'

const sendEmail = email => {
 // We don't want to be sending out emails while developing or testing.
 // Now we don't need to manually check environment variables anymore
 // Code to send email
}

export deafault isolate(sendMail)

// sendMail is now isolated. It will only run in production.
// To run it while testing, we can integrate it back.

And while testing:

import { integrate } from 'isograte'
// we import the isolated sendMail function
import sendMail from './isolatedSendMail'

it('should generate and send email properly', () => {
  const _sendMail = integrate(sendMail)
  // _sendMail is now integrated. Be carefull while calling it.
  // Even though sendMail calls other isolated functions,
  // they still remain isolated and won't run. You only need to worry about
  // sendMail while testing it
})

Was this page helpful to you?