Search code examples
javascriptnode.jstestingsinonstub

Stub functions before running script as child process


I have mostly only seen mocks and stubs used in automated testing. But I wanted to stub methods for manually testing my app. This way I can run my server and test my app manually in my browser and when I press a button to buy an item for example, the backend will have been stubbed so that the call to stripe is stubbed with a fake call to stripe.

I want to create a test environment to do this. In this test environment I want to stub some methods, like api calls to stripe. I would think one would create this test environment by writing a script that stubs methods and then launches the app from a child process after the stubs are set.

But I'm having trouble stubbing methods before launching a script as a child process. When I launch a file using child_process, stubbing isn't working.

To recreate:

  1. Go to this sandbox
  2. Go to the terminal and click the + button to open a non-read-only terminal
  3. Run node src/runStubbedScript.js

In the terminal you will get:

making an http request to Stripe. This may take a while...

But I would expect the stub to replace it and give me skipping call to stripe.

How do I stub methods before launching a script?

Code

index.js:

const stripeInterface = require('./stripeInterface');

stripeInterface.charge();

stripeInterface.js:

const stripe = {
  charge: () => console.log('making an http request to Stripe. This may take a while...'),
};
module.exports = stripe;

runStubbedScript.js
Here I try to stub the Stripe interface and then launch index.js:

const { exec } = require('child_process');
const sinon = require('sinon');
const stripe = require('./stripeInterface');

sinon.stub(stripe, 'charge').callsFake(() => console.log('skipping call to stripe'));
exec('node index.js', (error, stdout, stderr) => {
  console.log(`stdout: ${stdout}`);
  console.log(`stderr: ${stderr}`);
  if (error !== null) {
    console.log(`exec error: ${error}`);
  }
});


Solution

  • Instead of executing a child_process I realized I could just require the file and it would do what I wanted:

    const sinon = require('sinon');
    const stripe = require('./stripeInterface');
    
    sinon.stub(stripe, 'charge').callsFake(() => console.log('skipping call to stripe'));
    
    require('./index'); // this runs index and the stripe function is stubbed