Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/felixge/node-gently

A node.js module that helps with stubbing and behavior verification.
https://github.com/felixge/node-gently

Last synced: 4 days ago
JSON representation

A node.js module that helps with stubbing and behavior verification.

Awesome Lists containing this project

README

        

# Gently

[![Build Status](https://travis-ci.org/felixge/node-gently.svg?branch=master)](https://travis-ci.org/felixge/node-gently)
[![npm](https://img.shields.io/npm/v/gently.svg)](https://www.npmjs.com/package/gently)
[![Dependency Status](https://david-dm.org/felixge/node-gently.svg?theme=shields.io)](https://david-dm.org/felixge/node-gently)
[![Development Dependency Status](https://david-dm.org/felixge/node-gently/dev-status.svg?theme=shields.io)](https://david-dm.org/felixge/node-gently#info=devDependencies)

## Purpose

A node.js module that helps with stubbing and behavior verification. It allows you to test the most remote and nested corners of your code while keeping being fully unobtrusive.

## Features

* Overwrite and stub individual object functions
* Verify that all expected calls have been made in the expected order
* Restore stubbed functions to their original behavior
* Detect object / class names from obj.constructor.name and obj.toString()
* Hijack any required module function or class constructor

## Installation

Via [npm](http://github.com/isaacs/npm):

npm install gently@latest

## Example

Make sure your dog is working properly:
```javascript
function Dog() {}

Dog.prototype.seeCat = function() {
this.bark('whuf, whuf');
this.run();
}

Dog.prototype.bark = function(bark) {
require('sys').puts(bark);
}

const gently = new (require('gently'))
, assert = require('assert')
, dog = new Dog();

gently.expect(dog, 'bark', function(bark) {
assert.equal(bark, 'whuf, whuf');
});
gently.expect(dog, 'run');

dog.seeCat();
```
You can also easily test event emitters with this, for example a simple sequence of 2 events emitted by `fs.WriteStream`:
```javascript
const gently = new (require('gently'))
, stream = new (require('fs').WriteStream)('my_file.txt');

gently.expect(stream, 'emit', function(event) {
assert.equal(event, 'open');
});

gently.expect(stream, 'emit', function(event) {
assert.equal(event, 'drain');
});
```
For a full read world example, check out this test case: [test-incoming-form.js](http://github.com/felixge/node-formidable/blob/master/test/simple/test-incoming-form.js) (in [node-formdiable](http://github.com/felixge/node-formidable)).

## API

### Gently

#### new Gently()

Creates a new gently instance. It listens to the process `'exit'` event to make sure all expectations have been verified.

#### gently.expect(obj, method, [[count], stubFn])

Creates an expectation for an objects method to be called. You can optionally specify the call `count` you are expecting, as well as `stubFn` function that will run instead of the original function.

Returns a reference to the function that is getting overwritten.

#### gently.expect([count], stubFn)

Returns a function that is supposed to be executed `count` times, delegating any calls to the provided `stubFn` function. Naming your stubFn closure will help to properly diagnose errors that are being thrown:
```javascript
childProcess.exec('ls', gently.expect(function lsCallback(code) {
assert.equal(0, code);
}));
```
#### gently.restore(obj, method)

Restores an object method that has been previously overwritten using `gently.expect()`.

#### gently.hijack(realRequire)

Returns a new require functions that catches a reference to all required modules into `gently.hijacked`.

To use this function, include a line like this in your `'my-module.js'`.
```javascript
if (global.GENTLY) require = GENTLY.hijack(require);

const sys = require('sys');
exports.hello = function() {
sys.log('world');
};
```
Now you can write a test for the module above:
```javascript
const gently = global.GENTLY = new (require('gently'))
, myModule = require('./my-module');

gently.expect(gently.hijacked.sys, 'log', function(str) {
assert.equal(str, 'world');
});

myModule.hello();
```
#### gently.stub(location, [exportsName])

Returns a stub class that will be used instead of the real class from the module at `location` with the given `exportsName`.

This allows to test an OOP version of the previous example, where `'my-module.js'`.
```javascript
if (global.GENTLY) require = GENTLY.hijack(require);

const World = require('./world');

exports.hello = function() {
const world = new World();
world.hello();
}
```
And `world.js` looks like this:
```javascript
const sys = require('sys');

function World() {

}
module.exports = World;

World.prototype.hello = function() {
sys.log('world');
};
```
Testing `'my-module.js'` can now easily be accomplished:
```javascript
const gently = global.GENTLY = new (require('gently'))
, WorldStub = gently.stub('./world')
, myModule = require('./my-module')
, WORLD;

gently.expect(WorldStub, 'new', function() {
WORLD = this;
});

gently.expect(WORLD, 'hello');

myModule.hello();
```
#### gently.hijacked

An object that holds the references to all hijacked modules.

#### gently.verify([msg])

Verifies that all expectations of this gently instance have been satisfied. If not called manually, this method is called when the process `'exit'` event is fired.

If `msg` is given, it will appear in any error that might be thrown.

## License

Gently is licensed under the MIT license.