npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

jsmock

v1.0.1

Published

Mocking framework for javascript

Downloads

32

Readme

npm Package Build Status Coverage Status

jsmock

Mocking framework for javascript, inspired by googlemock C++ framework. This project is still under construction ...

Installation

jsmock is published on npm

npm install --save-dev jsmock

User Guide

All examples provided below assume using mocha/chai test framework, although jsmock can be used with any framework of your choice.

Mock provides an API to define and verify expectations on all function calls performed on reference to original object. A standard unit test involving mocks will consist of following steps:

  1. Mock external dependencies of the test subject
  2. Define expectations on created mocks
  3. Execute actual tests on the subject
  4. Verify mock objects
  5. Cleanup

Creating Mocks

const Mock = require('jsmock').Mock;

let foo = {
  bar: (a, b) => {
    return a + b
  }
};

let fooMock = new Mock(foo);

Now fooMock is a mock object wrapping foo. All functions of original object have been replaced and any call to foo.bar will cause an UnexpectedCall error to be thrown.

expect(foo.bar.bind(foo)).to.throw(Error);

Defining Expectations

Expectation is a main component of a mock oriented test. It describes what kind of interactions with mocked object are expected during test execution. In addition Expectation also defines the actions that should be taken to mock the original object behavior.

Expectation for given function is defined by 3 objects:

  • Matcher
  • Cardinality
  • Action List

Matcher decides if current function call is valid for the expectation. Usually it means that function was called with expected argument list. Cardinality describes how many times the expected call should occur. Consequently Action List provides actions to be performed by mocked object for each call.

General Syntax

Expectation is created by calling expectCall on mock object. Then it can be set up with dedicated methods:

fooMock.expectCall('bar')
  .matching(1, 4)
  .times(4)
  .willOnce((a, b) => a + b)
  .willRepeatedly((a, b) => a - b);

Above code will create expectation on call to foo.bar(1,4) that should happen exactly 4 times. On the first call sum of the arguments will be returned, following 3 call with return their difference.

Specifying Matcher

Matcher is an object checking that call of mocked function is valid for given expectation. If no explicit matcher is specified expectation will be executed for any call to mocked function. Matcher can be specified as a predicate or simply as an arguments list to be verified against actual call.

In jsmock matchers come in 3 flavours:

  • Predicate Matcher - applies call arguments to provided predicate
  • Strict Argument Matcher - call argument list must match exactly matcher argument list
  • Weak Argument Matcher - first N call arguments must match matcher argument list

Matcher can be specified during Expectation creation with expectCall function, or later with one of available Expectation methods.

| Method | Description | |--------|-------------| | Mock.expectCall(fn, ...args) | Creates an expectation with Strict Argument Matcher from ...args| | Expectation.matching(...args) | Creates a Strict Argument Matcher from ...args | | Expectation.with(...args) | Alias of Expectation.matching | | Expectation.matchingAtLeast(...args) | Creates a Weak Argument Matcher from ...args | | Expectation.withAtLest(...args) | Alias of Expectation.matchingAtLeast |

Predicate Matcher is created automatically if one of above methods is called with only one argument that happens to be a function.

fooMock.expectCall('bar', (a,b) => a > b); // Predicate Matcher
foo.bar(3,2); // OK - 3 > 2
foo.bar(1,4); // KO

fooMock.expectCall('bar', 1, 8); // Strict Argument Matcher
foo.bar(1,8); // OK
foo.bar(1,0); // KO 

fooMock.expectCall('bar').with(5,6); // Strict Argument Matcher
foo.bar(5,6); // OK
foo.bar(5,1); // KO 

fooMock.expectCall('bar').matchingAtLeast(3); // Weak Argument Matcher
foo.bar(3,6); // OK
foo.bar(3,9); // OK 
foo.bar(1,3); // KO 

Argument Type Matchers

jsmock comes with a family of predefined argument type matchers, that can be helpful if we care more about the type of argument provided to the call than its actual value.

| Matcher | Description | |---------|-------------| | Matcher.ANY | Checks only presence of an argument in a call, doesn't care about actual type | | Matcher.OBJECT | Checks if given argument is an object | | Matcher.NUMBER | Checks if given argument is a number | | Matcher.STRING | Checks if given argument is a string | | Matcher.BOOLEAN | Checks if given argument is a boolean | | Matcher.FUNCTION | Checks if given argument is a function | | Matcher.ARRAY | Checks if given argument is an array |

const Matcher = require('jsmock').Matcher;

fooMock.expectCall('bar').with(Matcher.ANY, Matcher.NUMBER);
foo.bar(1,2); // OK
foo.bar('a',2); // OK
foo.bar([1,2,3], true); // KO

Specifying Cardinality

Cardinality specifies number of expected calls to given function. jsmock provides two ways of specifying expectation cardinality. It can be provided explicitly through one of expectation methods, or it can be calculated automatically from list of specified actions. If cardinality is specified explicitly it takes precedence over one calculated from action list.

| Method | Description | |--------|-------------| | Expectation.times(N) | Matching call should occur exactly N times | | Expectation.atLeast(N) | Matching call should occur at least N times | | Expectation.atMost(N) | Matching call should occur at least once and at most N times | | Expectation.between(M,N) | Matching call should occur at least M times and at most N times |

fooMock.expectCall('bar').times(2); // Expect bar to be called twice
fooMock.expectCall('bar').atLeast(1); // Expect bar to be called at least one time
fooMock.expectCall('bar').atMost(4); // Expect bar to be called 1 - 4 times
fooMock.expectCall('bar').between(3,5); // Expect bar to be called 3 - 5 times

// Note that 
fooMock.expectCall('bar').atMost(MaxCallCount);
// is equivalent of 
fooMock.expectCall('bar').between(1, MaxCallCount);

Cardinality can be specified only once for given expectation.

Adding Actions

Action is an object encapsulating function to be executed instead of the original mocked object code. Each expectation can have multiple actions defined with specific cardinality. Actions are executed in the order of creation.

fooMock.expectCall('bar')
  .willOnce((a,b) => a * b) // First call will return multiplication of arguments
  .willTwice((a,b) => a + b) // Second and third will return sum of arguments
  .willRepeatedly((a,b) => b); // All following calls will return second argument

If action specifying method is feed with function it will use it as a callback for actual mocked function execution. If parameter of any other type is provided it will be returned to the caller at execution time.

fooMock.expectCall('bar')
  .willOnce(4) // Return 4 on first call
  .willTwice(7) // return 7 on next 2 calls
  .willRepeatedly(0); // All following calls will return 0

The willRepeatedly method specifies action with unlimited number of potential calls, thus any other attempt to add more actions to the expectation will cause error. Also note that willRepeatedly doesn't return expectation object so it isn't suitable for chaining.

In nodejs (and js in general) it's very common to provide callback as the last argument in the function call. Often the only purpose of the mock is to execute that callback with some predefined arguments. This kind of action can be created easily using will...Invoke versions of action create methods

fsMock.expectCall('readdir')
  .willOnceInvoke(null, ['a.js', 'b.js']);

// Which is equivalent of
fsMock.expectCall('readdir')
  .willOnce((path, cb) => cb(null, ['a.js', 'b.js']));

| Method | Description | |--------|-------------| | Expectation.willOnce(k) | Adds an action to be executed once | | Expectation.willTwice(k) | Adds an action to be executed twice | | Expectation.willRepeatedly(k) | Adds an action to be executed until expectation cardinality is fulfilled | | Expectation.willOnceInvoke(...args) | Adds an invoker action to be executed once | | Expectation.willTwiceInvoke(...args) | Adds an invoker action to be executed twice | | Expectation.willRepeatedlyInvoke(...args) | Adds an invoker action to be executed until expectation cardinality is fulfilled |

Verifying Mocks

Mock object will yield errors directly in case of unexpected calls or violation of cardinality upper bound (more calls than expected). Verification of cardinality lower bound has to be done explicitly by the user, at the end of the test.

let foo = new Foo();
let fooMock = new Mock(foo);
fooMock.expectCall('bar')
  .times(2) // Lower bound of the cardinality is 2
  .willRepeatedly(6);

expect(foo.bar()).to.be.equal(6); // We make only one call to bar 

fooMock.verify(); // Will throw Error 

Call to verify methods cleans up all previously setup expectations.

Cleaning Mocks

Creation of the mock over an existing object modifies its functions. To restore object to its original state you need to explicitly call cleanup method.

const fs = require('fs');
const Mock = require('jsmock').Mock;

let fsMock = new Mock(fs);

// Setup some expectations
fsMock.expectCall('readdir')
  .willOnce((path, cb) => cb(null, ['index.html']));

testedObject.doSomeStuff();

fsMock.verify();

// Once you don't need to use fs in your tests
fsMock.cleanup();

Examples

Some examples of potential "real life" usage can be found in example.js test file.