Skip to content

moeriki/jestdouble

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

39 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

jestdouble

jestdouble is an alternative mock/spy for jest.

npm version Build Status Coverage Status Known Vulnerabilities

Installation

$ npm install --save-dev jestdouble

Why

I wanted a mock/spy function that:

Quick start

All references to expect are jest.expect.

const jd = require('jestdouble');

const func = jd(); // create a jest double

func.returns(1, { times: 1 });
func.returns(2);

func(); // 1
func(); // 2
func(); // 2

expect(func).toHaveBeenCalledTimes(3);

Mocking results

Invoking a function

function sum(num1, num2) {
    return num1 + num2;
}
const mockedSum = jd(sum);
mockedSum(1, 2); // 3
const func = jd();
func.invokes(() => 1));
func(); // 1

Returning values

returning value

const func = jd();
func.returns(1);
func(); // 1

returning this

const object = {
  func: td()
};
object.func.returnsThis();
object.func(); // object

returning rejected error

const func = jd();
func.rejects(new Error('nope'));
func().catch((err) => {/* Error<nope> */});

returning resolved value

const func = jd();
func.resolves(1);
func().then((value) => {/* 1 */});

throwing value

const func = jd();
func.throws(new Error('nope'));
func(); // throws Error<nope>

calling back error

const func = jd();
func.callbacks(new Error('nope'));
func((err) => {/* Error<nope> */});

calling back value

const func = jd();
func.callbacks(null, 1);
func((err, value) => {/* null, 1 */});

Conditionally mocking results

calledWith

const func = jd();
func.calledWith('one').returns(1);
func(); // undefined
func('one'); // 1
func('one', 'two'); // undefined

calledStartingWith

const func = jd();
func.calledStartingWith('one').returns(1);
func(); // undefined
func('one'); // 1
func('one', 'two'); // 1

Mocking options

times

const func = jd();
func.calledWith('one').returns(1, { times: 1 });
func.returns(2, { times: 1 });
func.returns(3);

func('one'); // 1
func(); // 2
func('one'); // 3
func(); // 3

Verifying calls

jestdouble is compatible with jasmine assertions.

const func = jd();
func('one');
func('two');
func('three');
expect(func).toHaveBeenCalled();
expect(func).toHaveBeenCalledTimes(3);
expect(func).toHaveBeenCalledWith('one');

Conditionally verifying calls

with

const func = jd();
func('one', 'two');
expect(func.with('one')).not.toHaveBeenCalled();
expect(func.with('one', 'two')).toHaveBeenCalled();

startingWith

const func = jd();
func('one', 'two');
expect(func.startingWith('one')).toHaveBeenCalled();
expect(func.startingWith('one', 'two')).toHaveBeenCalled();

Matching

Both mocking results and verifying calls support smart value matching.

const func = jd();
func.calledWith((str) => str === 'one').returns(1);
func.calledWith(Number).returns(2);
func('one'); // 1
func(2); // 2
const func = jd();
func('two');
func('three');
expect(func.with(/^t/)).toHaveBeenCalledTimes(2);

Check the API of matchr to learn all the possibilities.

Matching options

There are three matching options.

const td = require('testdouble');

td.setMatchingOptions({
  matchPartialObjects: true,   // default: false
  matchPartialArrays: true,    // default: false
  matchOutOfOrderArrays: true, // default: false
});

const func = td();

func.calledWith([{ c: 3 }, { a: 1 }]).returns('OK');

func([{ a: 1, z: 26 }, { b: 2 }, { c: 3 }]); // 'OK'

setMatchingOptions delegates to matchr.setDefaultOptions.

API

Mock

jestdouble.invokes( arg:function [, options:object] )

jestdouble.returns( arg:* [, options:object] )

jestdouble.returnsThis( [options:object] )

jestdouble.resolves( arg:* [, options:object] )

jestdouble.rejects( arg:* [, options:object] )

jestdouble.callsback( arg:* [, options:object] ) // aliased as callbacks

jestdouble.throws( arg:* [, options:object] )

Conditional mock

jestdouble.calledWith( ...args:* ).invokes( arg:function [, options:object] )

jestdouble.calledWith( ...args:* ).returns( arg:* [, options:object] )

jestdouble.calledWith( ...args:* ).returnsThis( [options:object] )

jestdouble.calledWith( ...args:* ).resolves( arg:* [, options:object] )

jestdouble.calledWith( ...args:* ).rejects( arg:* [, options:object] )

jestdouble.calledWith( ...args:* ).callsback( arg:* [, options:object] ) // aliased as callbacks

jestdouble.calledWith( ...args:* ).throws( arg:* [, options:object] )

jestdouble.calledStartingWith( ...args:* ).invokes( arg:function [, options:object] )

jestdouble.calledStartingWith( ...args:* ) .returns( arg:* [, options:object] )

jestdouble.calledStartingWith( ...args:* ) .returnsThis( [options:object] )

jestdouble.calledStartingWith( ...args:* ) .resolves( arg:* [, options:object] )

jestdouble.calledStartingWith( ...args:* ) .rejects( arg:* [, options:object] )

jestdouble.calledStartingWith( ...args:* ) .callsback( arg:* [, options:object] ) // aliased as callbacks

jestdouble.calledStartingWith( ...args:* ) .throws( arg:* [, options:object] )

Mock options

  • times mock result N times

Verify

expect( jestdouble ).toHaveBeenCalled();

expect( jestdouble.with( ...args:* ) ).toHaveBeenCalled();

expect( jestdouble.startingWith( ...args:* ) ).toHaveBeenCalled();

Notes

Results order

Conditionally mocked results will always be returned in favour of mocked results without conditional arguments.

const func = td();
func.returns(Infinity);
func.calledWith('one').returns(1);
func(); // Infinity
func('one'); // 1
const func = td(() => 1);
func.calledWith('two').returns(2);
func(); // 1
func('two'); // 2

Credit

The name is inspired by jest and testdouble.js. API design is inspired by testdouble.js.

About

jestdouble is an alternative mock/spy for jest.

Resources

License

Stars

Watchers

Forks

Packages

No packages published