New Research: Supply Chain Attack on Axios Pulls Malicious Dependency from npm.Details
Socket
Book a DemoSign in
Socket

deprivation

Package Overview
Dependencies
Maintainers
1
Versions
29
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

deprivation

testing facilitation, by converting Unit Under Test to a sandboxed version, that exposes module internals without the need to export them.

latest
Source
npmnpm
Version
3.4.1
Version published
Weekly downloads
16
-30.43%
Maintainers
1
Weekly downloads
 
Created
Source

Deprivation

This module facilitate whitebox and blackbox testing (binding it with conventional UT and MT paradigms) of nodejs applications.

We define a module as a folder with implementations.

These are the two main modes of operation of the deprivation module:

  • whitebox unit

    • grants a full access to an object, without the need to export everything in order to test it. useful e.g. in TDD (test small increments without exposing every method), and writing fine-grained tests.
  • blackbox module

    • gives the public access to an object

Both modes enable auto mocking.

Behind the curtains it uses the Node's VM module, and plows the require.cache.

Usage

npm install deprivation

For running a complete suite of tests use the npm test command.

Example implementation (Unit Under Test).

    var glob = require('glob');
    var dep = require('./dep.js');

    var myPrivateFunc = function(param){
        return glob.GlobSync(param);
    };

    var publicFunc = function(param) {
        return myPrivateFunc(param);
    };

    var callAnotherGlob = function() {
        return dep('huhu');
    };

    module.exports.publicFunc = publicFunc;

Basic

An example test file.

    var chamber = require("deprivation").chamber;
    var session = chamber("./implementation.js");

    // uut - Unit Under Test
    var uut = session.whitebox();

    uut.publicFunc("blabla"); // nothing special. Will call private func, which calls the original glob.GlobSync.
    uut.myPrivateFunc("blabla"); // However... note that this func is not exported, but still accessible in a test!
    uut.glob.GlobSync("blabla") // or even this...

Replace dependencies

It's possible to inject any type of a test double: mock, spy, stub, fake, etc., into the UUT.

Example dependency of UUT.

    // dep.js
    module.exports = require('glob').GlobSync;

Right after the module is 'loaded'

  • the UUT code is 'loaded' (= all the require statements are executed in the UUT)
  • the dependencies are replaced after exposition of the UUT
  • replacement in not transitive!
// let's get rid of glob.GlobSync dependency
    uut.glob.GlobSync = function(){};

// all calls execute the dummy function
    uut.publicFunc('blabla');
    uut.myPrivateFunc('blabla');
    uut.glob.GlobSync('blabla');

// ...but not this one!
    uut.callAnotherGlob();

Through an option

Leads to a different result:

  • if the replacement is an object, the require initialization code of the replaced dependancies is not executed
  • if the replacement is a string (as in the require statement), the require initialization code is executed
  • replacement is transitive (it is replaced globally)
    var myGlob = {GlobSync: function() {return './.ssh/id_rsa.priv'}}
    var session = chamber('./implementation.js', {replace:[{'glob': myGlob}]});
    var uut = session.whitebox();

    // all calls return './.ssh/id_rsa.priv'
    uut.glob.GlobSync('something');
    uut.callAnotherGlob('something');

Blackbox, through an option, with more automation

If a function exists, which accepts an object, and returns its test double,

// A jasmine spy-maker example

    var myReplacer = function (obj) {
        Object.keys(obj).forEach(function (item) {
            spyOn(obj, item);
        });
    };

it can be passed on with the replacer option.

    seance = chamber("myModule/impl.js", {replace: ['glob', '../*'], replacer: myReplacer});

In the above example

  • the magical '../*' string means that all implementations outside of myModule folder will be automatically transformed into spies. This omits the node_module folder.
  • due to the above, the glob package is added explicitly, and will be automatically turned into a mock,

'*' replaces all implementations (within the same folder too!)

An example test suite (jasmine/mocha):

    beforeEach(function () {
        sut = seance.blackbox();
        spies = seance.getTestDoubles();
    });

spies above are the spy objects references, stored in a dictionary. This allows to work with objects, that are inaccessible from the module's public interface.

The expectation may be set, using the obtained references.

    it('uses GlobSync', function () {
        sut.arrangeHeapDumps('bleble');
        expect(spies['node_modules/glob/glob.js'].GlobSync).toHaveBeenCalled();
    });

Test doubles are accessed using the path relative to the process current directory. This is the most readable way to specify, which test double object is referenced (the glob package may be used by other sub-packages, in different versions, etc.)

Clone the project from the repository and refer to the test/*.* files for more examples.

Keywords

unit test

FAQs

Package last updated on 17 Mar 2016

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts