TNG/sinon-helpers

Name: sinon-helpers

Owner: TNG Technology Consulting GmbH

Description: Create easily configurable sinon stubs that mimic constructors and keep track of their instances

Created: 2016-09-23 13:37:04.0

Updated: 2018-05-02 12:57:37.0

Pushed: 2018-05-02 12:57:35.0

Homepage: null

Size: 237

Language: JavaScript

GitHub Committers

UserMost Recent Commit# Commits

Other Committers

UserEmailMost Recent Commit# Commits

README

sinon-helpers

Create easily configurable sinon stubs that mimic constructors and keep track of their instances.

npm codecov.io JavaScript Style Guide npm David Greenkeeper badge semantic-release

Motivation

Especially when working with the new ES6 classes, a common problem in unit testing is to find out if a module creates instances of a class using the right constructor arguments and which methods are called on these instances. Moreover, it would be nice to be able to control that these classes are properly stubbed i.e. that in our tests, none of the original class code is executed.

New test dependencies can be easily injected with rewire or proxyquire for node testing and inject-loader or babel-plugin-rewire for webpack testing. The question remains how the stated goal can be achieved using a mocking library such as sinon.

In the examples, we want to mock a constructor MyConstructor.

Simple approaches

To really solve this problem, we will need to create our own custom constructor. sinon-helpers is a library that offers an easy and generic solution to this problem.

What sinon-helpers offers
Installation
install --save-dev sinon-helpers

or

 add --dev sinon-helpers
Usage
sh = require('sinon-helpers') // CommonJS
rt * as sh from 'sinon-helpers' // ES6
lternative: import {getStubConstructor, getSpyConstructor, returning} from 'sinon-helpers'

reate a constructor mimicking a given constructor
MyStubConstructor = sh.getStubConstructor(MyConstructor)

ou may also add new methods and provide return values to existing methods
ubConstructor = MyStubConstructor.withMethods('method1', sh.returning(1), 'method2', sh.returningThis)

reate a constructor that calls through to the original constructor
ith spies on all methods and having a few methods stubbed
MySpyConstructor = sh.getSpyConstructor(MyConstructor).withStubs('method1', 'method2', sh.returning(true))

reate an object with the given methods as stubs
myMethods = sh.getMethodStubs('method1', 'method2', sh.returning('Hello'))
API
getStubConstructor(<OriginalConstructor>)

Returns a StubConstructor mimicking the given constructor OriginalConstructor. When called with new, this constructor creates an object with stubs for any methods of the prototype object of ConstructorName. If you call getStubConstructor without any arguments, you receive a StubConstructor without any pre-defined methods. Any StubConstructor features several methods to add methods and query created instances.

StubConstructor API

A StubConstructor has the following methods:

getSpyConstructor(OriginalConstructor)

Returns a SpyConstructor of the given constructor OriginalConstructor. A SpyConstructor is similar to a StubConstructor except for the following differences:

This is useful if you need to preserve the constructor's functionality while being able to track its instances. Note however that having to rely on SpyConstructors instead of StubConstructors may be an indication of strong couplings in you software that are generally a sign that your architecture could be improved.

SpyConstructor API

A SpyConstructor has the following methods:

getMethodStubs(methodName1 <, methodName2 ...>)

Returns an object containing the given methods as stubs. Again, getMethodStubs allows you to specify stub return values.

Specifying stub return values

sinon-helpers allows you to specify return values for any created stub methods:

Stub = sh.getStubConstructor(MyConstructor).withMethods(
         'method1', sh.returning(3),
         'method2', sh.returningThis,
         'method3'
       )

This creates a StubConstructor where any instance has the three methods .method1(), .method2() and .method3(). .method1() always returns 3, .method2() returns its this value and .method3() returns undefined. This can also be used to add return values to prototype methods. This also works with SpyConstrucors:

Spy = sh.getSpyConstructor(MyConstructor).withStubs(
         'method1', sh.returning(3),
         'method2', sh.returningThis,
         'method3'
       )

This creates a SpyConstructor where for any instance, .method1(), .method2() and .method3() are stubbed, and .method1() always returns 3, .method2() returns its this value and .method3() returns undefined.
With getMethodStubs(), you can do the same:

methodStubs = sh.getMethodStubs(
                 'method1', sh.returning(3),
                 'method2', sh.returningThis,
                 'method3'
              )
Contributing

Feel like this library could do more for you? Found an issue with your setup? Want to get involved? Then why not contribute by raising an issue or creating a pull-request!


This work is supported by the National Institutes of Health's National Center for Advancing Translational Sciences, Grant Number U24TR002306. This work is solely the responsibility of the creators and does not necessarily represent the official views of the National Institutes of Health.