Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Jest - mock function in 'child_process' package

I'm writing unit tests and which to mock the 'exec' method in package 'child_process'.

__mocks__/child_process.js

const child_process = jest.genMockFromModule('child_process');
child_process.exec = jest.fn()

module.exports = child_process;

This is the test file:

const fs = require('fs-extra'),
      child_process = require('child_process'),
      runCassandraMigration = require('../../lib/runCassandraMigration.js')

const defaultArguments = () => {
  return {
    migration_script_path: './home',
    logger: {
      error: function () {}
    }
  };
}

jest.mock("fs-extra")
jest.mock("child_process")

describe('Running cassandra migration tests', function () {
  describe('successful flow', function () {
    it('Should pass without any errors ', async function () {
        let args = defaultArguments();
        let loggerSpy = jest.spyOn(args.logger, 'error')

        fs.remove.mockImplementation(() => {Promise.resolve()})
        child_process.exec.mockImplementation(() => {Promise.resolve()})

        await runCassandraMigration(args.migration_script_path, args.logger)
    });
  });

When I run the test I get the following error:

child_process.exec.mockImplementation is not a function

The module I test

const fs = require('fs-extra')
const promisify = require('util').promisify
const execAsync = promisify(require('child_process').exec)

module.exports = async (migration_script_path, logger) => {
  try {
    console.log()
    const {stdout, stderr} = await execAsync(`cassandra-migration ${migration_script_path}`)
    logger.info({stdout: stdout, stderr: stderr}, 'Finished runing cassandra migration')
    await fs.remove(migration_script_path)
  } catch (e) {
    logger.error(e, 'Failed to run cassandra migration')
    throw Error()
  }
}

Please advise.

like image 643
David Faizulaev Avatar asked May 08 '18 12:05

David Faizulaev


1 Answers

A late... answer?...

Yesterday I got the same error and the problem was that I wasn't calling jest.mock('child_process') in my test file.

Jest documentation says that when mocking Node's core modules calling jest.mock('child_process') is required. I see you do this but for some reason it is not working (maybe Jest is not hoisting it to the top).

Anyways, with Jest version 24.9.0 I don't get the child_process.exec.mockImplementation is not a function error but get some other errors because your test is not well implemented.

To make your test work I:

Added info: function () {}, inside logger

Updated the implementation of exec to child_process.exec.mockImplementation((command, callback) => callback(null, {stdout: 'ok'})) And also (not necessary for the test to pass) updated the implementation of fs.remove to fs.remove.mockImplementation(() => Promise.resolve())

Like this:

const fs = require('fs-extra'),
      child_process = require('child_process'),
      runCassandraMigration = require('./stack')

const defaultArguments = () => {
  return {
    migration_script_path: './home',
    logger: {
      info: function () {},
      error: function () {}
    }
  };
}

jest.mock("fs-extra")
jest.mock("child_process")

describe('Running cassandra migration tests', function () {
  describe('successful flow', function () {
    it('Should pass without any errors ', async function () {
        let args = defaultArguments();
        let loggerSpy = jest.spyOn(args.logger, 'error')

        fs.remove.mockImplementation(() => Promise.resolve())
        child_process.exec.mockImplementation((command, callback) => callback(null, {stdout: 'ok'}))

        await runCassandraMigration(args.migration_script_path, args.logger)
    });
  });
});
like image 179
Daniel Muñoz Avatar answered Nov 11 '22 06:11

Daniel Muñoz