aidanharris
aidanharris

Reputation: 157

Replace functions in nodejs module with mock functions

I'm creating a small project in nodejs that is a wrapper for an API. I'm writing some unit tests using nodeunit and need to inject various mock functions into the module (for example a function that simulates making a HTTP request to the server and outputs various different responses to test my code against).

The question I have is how do I inject these functions into my module?

I've identified two methods that should theoretically work as follows:

Method 1

Rename the folders of the modules I would like to replace and add a new folder containing the code I'd like to inject e.g:

./node_modules/request -> ./node_modules/request.tmp
./tests/myRandomFunction -> ./node_modules/request

After performing the tests I would then do the opposite:

./node_modules/request -> ./tests/myRandomFunction
./node_modules/request.tmp -> ./node_modules/request

This seems rather hacky and is not something I'd like to attempt even though it should theoretically work.

Method 2

This is my preferred method utilising my modules initialisation. My module takes a JSON object that can contain various options as follows:

var module = require('./module')({
  option1: '',
  option2: '',
  ...
});

I am planning on adding a key to this JSON object called '_testing' with the value of a JSON object containing various functions for example:

var module = require('./module')({
  _testing: {
    request: function() {return false;}
  }
});

In my module I could then do the following:

 

eval(''+key+' = this._testing.'+key) //eval('request = this._testing.request')
/*
eval can be dangerous I should probably perform some validation for example is key a function we want to be replaced? Can I check if nodeunit is testing my module and if it isn't don't do anything?
*/

Is there a better way to inject / replace a function in my module for testing purposes?

Upvotes: 3

Views: 9724

Answers (2)

Jakemmarsh
Jakemmarsh

Reputation: 4671

This is called "mocking" or "stubbing". It's a common necessity while testing, and there's a variety of libraries. Possibly the most popular is Sinon.

With Sinon you can do something like var stub = sinon.stub(request, [methodName]).returns(false) (or any other return value). You can also do things like stub.expects(42) to assert that the function receives that as a parameter when invoked.

Upvotes: 1

dainis
dainis

Reputation: 86

I have used Mockery for this purpose

And for testing HTTP calls Nock

They both offer a lot cleaner approach

Upvotes: 2

Related Questions