Narwhals Poke Mammals

    spyfactory

    0.3.5 • Public • Published

    spyFacory

    NPM Version NPM Downloads License MIT Dependencies

    What?

    A spy factory creates service fakes within node, that enforce the call contract on methods.

    Why?

    When testing complicated interactions, sometimes we are stuck testing the interactions between services. The spy factory builds these mock objects.

    Note

    Touch Integration is the idea that a fake should uphold the contract the original object held. This way if the object undertest is changed such that it now violates that contract, tests will fail and not production.

    Spy facory uses stubcontractor to ensure touch intigration.

    Note

    This library works really well with approval-result-factory


    Initialization

    Spy Factory needs to be initialized with a stubcontractor that is configured for your project.

    const stubcontractor = require('./stubcontractorConfig');
    const spyFactory = require('spyfactory')(stubcontractor);

    Basic Usage

    const fakeObject = spyFactory(
                    'myModule',
                    [
                        'add'
                    ]
                );

    This finds a file called 'myModule'. In that file it locates a function called 'add'. It then creates an object that enforces the contract of add.

    Add also has a sinon spy to the add method.

    this spy can be retrieved by:

    const spy = fakeObject.add.getOnCallAction();

    Last item of note is the fake object has a property called '__name'. This is by default set to the name given in the first parameter. In this case, 'myModule'.


    Adding an action to be performed

    const fakeObject = spyFactory(
                    'myModule',
                    [
                        ['add', function (a, b) { return a + b; }]
                    ]
                );

    If an array is given instead of a string, the second parameter is a function which will be called each time the method is called.

    It is simular to:

    const fakeObject = {
        add: sinon.spy(function (a, b) { return a + b; })
    };

    Except that it will also do touch intigration.


    Not spying on a method

    const fakeObject = spyFactory(
                    'myModule',
                    [
                        ['add', (a, b) => a + b, false]
                    ]
                );

    If you do not want to spy on a function, you can add a third item to the the array. If this item is the boolean false then the function will be faked but without a spy attached. It will however still inforce touch intigration.


    renameTo

    Sometimes the internal implimentation uses a method who's name does not match what is attached to the object the service exports. Then it is handy to rename that service.

    Example

    // This is the module the spy is created from.
    // adder.js
    function addAndThenAddAgain(a, b c) {
        return (a + b + c) * 2;
    }
     
    module.exports = {
        addTwice: addAndThenAddAgain
    };

    To create a fake of the above service:

    let adderFake = spyFactory(
        'adder',
        [
            'addAndThenAddAgain'
        ]
    );
     
    adderFake.addAndThenAddAgain.renameTo('addTwice');

    After renameTo is called, the addAndThenAddAgain is no longer a function on the adderFake. It has been renamed to addTwice.

    Call a callback

    Spy factory, comes with a nice helper. If your methods conform to the convention that the callback is the last function and the function has the following signature:

    (error, data) => undefined

    Then spy factory has a tool that will help ensure that the callback is called.

    const fakeObject = spyFactory(
                    'myModule',
                    [
                        ['asyncAdd', spyFactory.callCallback(null, 4)],
                        ['asyncSubtract', spyFactory.callCallback()]
                    ]
                );

    This creates a function that looks something like this:

    function callbackCaller(...args) {
        const callback = args.pop();
        callback(givenError, givenData);
    }

    Where 'givenError' and 'givenData' are the parameters passed to 'callCallback'.


    Call a callback via

    This allows the callback to be passed to a function that will call the callback.

    let stuffHappend = false;
     
    const fakeObject = spyFactory(
                    'myModule',
                    [
                        ['asyncAdd', spyFactory.callCallbackVia(callback => callback(null, stuffHappend))],
                    ]
                );

    Later ..

    stuffHappend = true;
    fakeObject.asyncAdd((error, data) => {
        if(data) {
            console.log('Got it!');
        }
    });

    Because stuffHappend is later set to true then the console will log "Got it!".

    Keywords

    none

    Install

    npm i spyfactory

    DownloadsWeekly Downloads

    31

    Version

    0.3.5

    License

    MIT

    Unpacked Size

    23.9 kB

    Total Files

    20

    Last publish

    Collaborators

    • jasonkerney