Giter VIP home page Giter VIP logo

proxyquire's Introduction

proxyquire Build Status

Proxies nodejs's require in order to make overriding dependencies during testing easy while staying totally unobtrusive.

If you want to stub dependencies for your client side modules, try proxyquireify, a proxyquire for browserify v2 or proxyquire-universal to test in both Node and the browser.

Features

  • no changes to your code are necessary
  • non overridden methods of a module behave like the original
  • mocking framework agnostic, if it can stub a function then it works with proxyquire
  • "use strict" compliant

Example

foo.js:

var path = require('path');

module.exports.extnameAllCaps = function (file) {
  return path.extname(file).toUpperCase();
};

module.exports.basenameAllCaps = function (file) {
  return path.basename(file).toUpperCase();
};

foo.test.js:

var proxyquire =  require('proxyquire')
  , assert     =  require('assert')
  , pathStub   =  { };

// when no overrides are specified, path.extname behaves normally
var foo = proxyquire('./foo', { 'path': pathStub });
assert.strictEqual(foo.extnameAllCaps('file.txt'), '.TXT');

// override path.extname
pathStub.extname = function (file) { return 'Exterminate, exterminate the ' + file; };

// path.extname now behaves as we told it to
assert.strictEqual(foo.extnameAllCaps('file.txt'), 'EXTERMINATE, EXTERMINATE THE FILE.TXT');

// path.basename and all other path module methods still function as before
assert.strictEqual(foo.basenameAllCaps('/a/b/file.txt'), 'FILE.TXT');

You can also replace functions directly:

get.js:

var get    = require('simple-get');
var assert = require('assert');

module.exports = function fetch (callback) {
  get('https://api/users', callback);
};

get.test.js:

var proxyquire = require('proxyquire').noCallThru();
var assert = require('assert');

var fetch = proxyquire('./get', {
  'simple-get': function (url, callback) {
    process.nextTick(function () {
      callback(null, { statusCode: 200 })
    })
  }
});

fetch(function (err, res) {
  assert(res.statusCode, 200)
});

Table of Contents generated with DocToc

Usage

Two simple steps to override require in your tests:

  • add var proxyquire = require('proxyquire'); to top level of your test file
  • proxyquire(...) the module you want to test and pass along stubs for modules you want to override

API

proxyquire({string} request, {Object} stubs)

  • request: path to the module to be tested e.g., ../lib/foo
  • stubs: key/value pairs of the form { modulePath: stub, ... }
    • module paths are relative to the tested module not the test file
    • therefore specify it exactly as in the require statement inside the tested file
    • values themselves are key/value pairs of functions/properties and the appropriate override

Preventing call thru to original dependency

By default proxyquire calls the function defined on the original dependency whenever it is not found on the stub.

If you prefer a more strict behavior you can prevent callThru on a per module or contextual basis. If your stub is a class or class instance rather than a plain object, you should disable callThru to ensure that it is passed through with the correct prototype.

class MockClass {
  static '@noCallThru' = true;
}

var foo = proxyquire('./foo', {
  './my-class': MockClass
});
class MockClass {
  get '@noCallThru'() {
    return true;
  }
}

var foo = proxyquire('./foo', {
  './my-class-instance': new MockClass()
});

If callThru is disabled, you can stub out modules that don't even exist on the machine that your tests are running on. While I wouldn't recommend this in general, I have seen cases where it is legitimately useful (e.g., when requiring global environment configs in json format that may not be available on all machines).

Prevent call thru on path stub:

var foo = proxyquire('./foo', {
  path: {
      extname: function (file) { ... }
    , '@noCallThru': true
  }
});

Prevent call thru for all future stubs resolved by a proxyquire instance

// all stubs resolved by proxyquireStrict will not call through by default
var proxyquireStrict = require('proxyquire').noCallThru();

// all stubs resolved by proxyquireNonStrict will call through by default
var proxyquireNonStrict = require('proxyquire');

Re-enable call thru for all future stubs resolved by a proxyquire instance

proxyquire.callThru();

Call thru configurations per module override callThru():

Passing @noCallThru: false when configuring modules will override noCallThru():

var foo = proxyquire
    .noCallThru()
    .load('./foo', {

        // no calls to original './bar' methods will be made
        './bar' : { toAtm: function (val) { ... } }

        // for 'path' module they will be made
      , path: {
          extname: function (file) { ... }
        , '@noCallThru': false
        }
    });

All together, now

var proxyquire = require('proxyquire').noCallThru();

// all methods for foo's dependencies will have to be stubbed out since proxyquire will not call through
var foo = proxyquire('./foo', stubs);

proxyquire.callThru();

// only some methods for foo's dependencies will have to be stubbed out here since proxyquire will now call through
var foo2 = proxyquire('./foo', stubs);

Using proxyquire to simulate the absence of Modules

Some libraries may behave differently in the presence or absence of a package, for example:

var cluster;
try {
  cluster = require('cluster');
} catch(e) {
  // cluster module is not present.
  cluster = null
}
if (cluster) {
  // Then provide some functionality for a cluster-aware version of Node.js
} else {
  // and some alternative for a cluster-unaware version.
}

To exercise the second branch of the if statement, you can make proxyquire pretend the package isn't present by setting the stub for it to null. This works even if a cluster module is actually present.

var foo = proxyquire('./foo', { cluster: null });

Forcing proxyquire to reload modules

In most situations it is fine to have proxyquire behave exactly like nodejs require, i.e. modules that are loaded once get pulled from the cache the next time.

For some tests however you need to ensure that the module gets loaded fresh everytime, i.e. if that causes initializing some dependency or some module state.

For this purpose proxyquire exposes the noPreserveCache function.

// ensure we don't get any module from the cache, but to load it fresh every time
var proxyquire = require('proxyquire').noPreserveCache();

var foo1 = proxyquire('./foo', stubs);
var foo2 = proxyquire('./foo', stubs);
var foo3 = require('./foo');

// foo1, foo2 and foo3 are different instances of the same module
assert.notStrictEqual(foo1, foo2);
assert.notStrictEqual(foo1, foo3);

proxyquire.preserveCache allows you to restore the behavior to match nodejs's require again.

proxyquire.preserveCache();

var foo1 = proxyquire('./foo', stubs);
var foo2 = proxyquire('./foo', stubs);
var foo3 = require('./foo');

// foo1, foo2 and foo3 are the same instance
assert.strictEqual(foo1, foo2);
assert.strictEqual(foo1, foo3);

Globally override require

Use the @global property to override every require of a module, even transitively.

Caveat

You should think very hard about alternatives before using this feature. Why, because it's intrusive and as you'll see if you read on it changes the default behavior of module initialization which means that code runs differently during testing than it does normally.

Additionally it makes it harder to reason about how your tests work.

Yeah, we are mocking fs three levels down in bar, so that's why we have to set it up when testing foo

WAAAT???

If you write proper unit tests you should never have a need for this. So here are some techniques to consider:

  • test each module in isolation
  • make sure your modules are small enough and do only one thing
  • stub out dependencies directly instead of stubbing something inside your dependencies
  • if you are testing bar and bar calls foo.read and foo.read calls fs.readFile proceed as follows
    • do not stub out fs.readFile globally
    • instead stub out foo so you can control what foo.read returns without ever even hitting fs

OK, made it past the warnings and still feel like you need this? Read on then but you are on your own now, this is as far as I'll go ;)

Watch out for more warnings below.

Globally override require during module initialization

// foo.js
var bar = require('./bar');

module.exports = function() {
  bar();
}

// bar.js
var baz = require('./baz');

module.exports = function() {
  baz.method();
}

// baz.js
module.exports = {
  method: function() {
    console.info('hello');
  }
}

// test.js
var bazStub = {
  method: function() {
    console.info('goodbye');
  }
};
  
var stubs = {
  './baz': Object.assign(bazStub, {'@global': true}) 
};

var proxyquire = require('proxyquire');

var foo = proxyquire('./foo', stubs);
foo();  // 'goodbye' is printed to stdout

Be aware that when using global overrides any module initialization code will be re-executed for each require.

This is not normally the case since node.js caches the return value of require, however to make global overrides work , proxyquire bypasses the module cache. This may cause unexpected behaviour if a module's initialization causes side effects.

As an example consider this module which opens a file during its initialization:

var fs = require('fs')
  , C = require('C');

// will get executed twice
var file = fs.openSync('/tmp/foo.txt', 'w');

module.exports = function() {
  return new C(file);
};

The file at /tmp/foo.txt could be created and/or truncated more than once.

Why is proxyquire messing with my require cache?

Say you have a module, C, that you wish to stub. You require module A which contains require('B'). Module B in turn contains require('C'). If module B has already been required elsewhere then when module A receives the cached version of module B and proxyquire would have no opportunity to inject the stub for C.

Therefore when using the @global flag, proxyquire will bypass the require cache.

Globally override require during module runtime

Say you have a module that looks like this:

module.exports = function() {
  var d = require('d');
  d.method();
};

The invocation of require('d') will happen at runtime and not when the containing module is requested via require. If you want to globally override d above, use the @runtimeGlobal property:

var stubs = {
  'd': {
    method: function(val) {
      console.info('hello world');
    },
    '@runtimeGlobal': true
  }
};

This will cause module setup code to be re-executed just like @global, but with the difference that it will happen every time the module is requested via require at runtime as no module will ever be cached.

This can cause subtle bugs so if you can guarantee that your modules will not vary their require behaviour at runtime, use @global instead.

Configuring proxyquire by setting stub properties

Even if you want to override a module that exports a function directly, you can still set special properties like @global. You can use a named function or assign your stub function to a variable to add properties:

function foo () {}
proxyquire('./bar', {
  foo: Object.assign(foo, {'@global': true})
});

And if your stub is in a separate module where module.exports = foo:

var foostub = require('../stubs/foostub');
proxyquire('bar', {
  foo: Object.assign(foostub, {'@global': true})
});

Backwards Compatibility for proxyquire v0.3.x

Compatibility mode with proxyquire v0.3.x has been removed.

You should update your code to use the newer API but if you can't, pin the version of proxyquire in your package.json file to ~0.6 in order to continue using the older style.

Examples

We are testing foo which depends on bar:

// bar.js module
module.exports = {
    toAtm: function (val) { return  0.986923267 * val; }
};

// foo.js module
// requires bar which we will stub out in tests
var bar = require('./bar');
[ ... ]

Tests:

// foo-test.js module which is one folder below foo.js (e.g., in ./tests/)

/*
 *   Option a) Resolve and override in one step:
 */
var foo = proxyquire('../foo', {
  './bar': { toAtm: function (val) { return 0; /* wonder what happens now */ } }
});

// [ .. run some tests .. ]

/*
 *   Option b) Resolve with empty stub and add overrides later
 */
var barStub = { };

var foo =  proxyquire('../foo', { './bar': barStub });

// Add override
barStub.toAtm = function (val) { return 0; /* wonder what happens now */ };

[ .. run some tests .. ]

// Change override
barStub.toAtm = function (val) { return -1 * val; /* or now */ };

[ .. run some tests .. ]

// Resolve foo and override multiple of its dependencies in one step - oh my!
var foo = proxyquire('./foo', {
    './bar' : {
      toAtm: function (val) { return 0; /* wonder what happens now */ }
    }
  , path    : {
      extname: function (file) { return 'exterminate the name of ' + file; }
    }
});

More Examples

For more examples look inside the examples folder or look through the tests

Specific Examples:

proxyquire's People

Contributors

achingbrain avatar bendrucker avatar bitsoflogic avatar bvalerius avatar danielmoore avatar davidbau avatar delaguilaluis avatar dsommerich avatar flesler avatar jakemmarsh avatar jbcpollak avatar jwalton avatar kamilogorek avatar klausbayrhammer avatar konklone avatar linusu avatar loujaybee avatar markherhold avatar maxnanasy avatar minrwhite avatar pdehaan avatar pghalliday avatar realityking avatar reggi avatar rus0000 avatar sonicdoe avatar thekashey avatar thlorenz avatar timgates42 avatar voitau avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

proxyquire's Issues

Multiple proxyquires of the same module returns undefined in all responses but the first one

I'm stubing a dependency using proxyquire.
In these tests, I'm using mocha and chai, like:

var proxyquire =  require('proxyquire').noPreserveCache();
var expect = require('chai').expect;
var done = require('chai').done;
var Q = require('q');
var objJSON = require('../resources/objJSON');

describe("Service", function() {

    describe("MyService", function() {

        describe("findAll() function", function() {

            it("should call db methods", function() {

                var myMockedService1 = proxyquire.load('../../app/services/myService', {
                    './db': {
                        select: function (field) {
                            return {
                                table: function (table) {
                                    var deferred = Q.defer();
                                    deferred.resolve(objJSON);
                                    return deferred.promise;
                                }
                            };
                        }
                    }
                });

                // myMockedService is now correctly mocked
                // BUT if I do another proxyquire just like the one done above, I get undefined as answer !!

                myMockedService.findAll().then(function(obj) {
                    expect(JSON.stringify(obj)).equal(JSON.stringify(objJSON));
                    done();
                });
            });
        });
    });
});

The first proxyquire works gret, but if I repeat another one next to the first one, it returns undefined as answer.
Could anyone point me if I'm missing some initialization of proxyquire if I'll require the same module multiple times? This blocks the tests by now. Thanks !!

Mocking internal class

Hello
I'm trying need to mock third party class (
This is code to be tested:

/myclas.js/
tps = require('tps');
myClass.prototype.myFunction(){
tpsInstance = tps.InClass();
.....
};
Unit test code

tps = proxyquire('myclass',{tps:tpsStub});
....

/tpsStub/

function tpsStub() {
this.InClass() = function(){
.....
}
}
When called tpsInstance = tps.InClass(); (from code above) - tpsStub created but trying to instantiate REAL InClass class The question: how can I create stub for InClass ? What was wrong in code above?
Thanks in advance

Override globals

Would be great if proxyquire could override globals ร  la rewire.

Use case: mocking properties of the process object.

Request: ability to stub non-existent modules

Often, your dev environment does not match your production environment. Some custom system modules cannot be installed on my local laptop dev machine, and it would be extremely handy to be able to stub modules that are otherwise not available on the system.

Perhaps this is via an explicit flag, such that you have to proactively specify it, so as not to introduce typo errors.

A simple try/catch around the require, and then returning just the stub if require cannot find the module should suffice.

Thanks!

Proxyquire messes up with columns

I wanted to mock the chalk module used in ESLint; I might have forgotten about sth and I got an error in mocha:

  3) formatter:stylish when passed one file not found message should return a string without line and column:
     TypeError: Cannot read property 'length' of undefined
      at dotindex (./eslint/node_modules/text-table/index.js:59:31)
      at ./eslint/node_modules/text-table/index.js:11:21
      at Array.forEach (native)
      at forEach (./eslint/node_modules/text-table/index.js:73:31)
      at ./eslint/node_modules/text-table/index.js:10:9
      at Array.reduce (native)
      at reduce (./eslint/node_modules/text-table/index.js:63:30)
      at module.exports (./eslint/node_modules/text-table/index.js:9:20)
      at ./eslint/lib/formatters/stylish.js:9:1767
      at Array.forEach (native)
      at module.exports (./eslint/lib/formatters/stylish.js:9:1244)
      at Context.<anonymous> (./eslint/tests/lib/formatters/stylish.js:197:26)
      at Test.Runnable.run (./eslint/node_modules/mocha/lib/runnable.js:211:32)
      at Runner.runTest (./eslint/node_modules/mocha/lib/runner.js:358:10)
      at ./eslint/node_modules/mocha/lib/runner.js:404:12
      at next (./eslint/node_modules/mocha/lib/runner.js:284:14)
      at ./eslint/node_modules/mocha/lib/runner.js:293:7
      at next (./eslint/node_modules/mocha/lib/runner.js:237:23)
      at Object._onImmediate (./eslint/node_modules/mocha/lib/runner.js:261:5)
      at processImmediate [as _immediateCallback] (timers.js:336:15)

Look at ./eslint/lib/formatters/stylish.js:9:1244 - this file definitely doesn't have such long lines. It's hard to see where an error occurs since there is actually nothing in this line: https://github.com/eslint/eslint/blob/0da23b8f365e0cb1e60e0fc456d8c46735e3a1b2/lib/formatters/stylish.js#L9

fail for non-existing path?

When I stub a path that does not exist, no error is thrown (correct me if I'm wrong). To prevent confusion, It would be very helpful to not silently accept ineffective stubs.

Cannot use with transpiled modules

Following #64, I still cannot use babel-node test.js, proxyquire will have no effect:

module.js

var dep = require('dep');
console.log(dep);

test.js

var proxyquire = require('proxyquire');
var mod = proxyquire('./module', {dep: function(){console.log('weee')}});

In a terminal:

babel-node test.js
# output contains the original dep

What can I do?

Working with relative paths

Writing the following seems impossible:

var log = proxyquire('./log', {"../config", {}});

Is there something wrong in this?
Thanks for your help.

Proxyquire does not override dependencies for one module only.

I want to test one module that makes use of the fs module.
So I stubbed out fs.existsSync and everything was working nicely. That was until I got to the part where I also needed to create a stub for fs.readFileSync.
Suddenly it all broke. I took me a while to realize that that's because I import another module that also uses fs.readFileSync.
I had also proxyquired that dependency so I didn't expect that.
What happened is that even though I had a complete mock for the module, proxyquire still loaded it.

So my question is, is there a way to tell proxyquire to either only replace the dependency once, in the module I actually requested, or if I can keep it from trying to load the dependency at all if I have a complete mock and don't just need to stub it.
@noCallThru does not work for this. It still loads the module, calls fs.readFileSync and then dies.

Paths passed to proxyquire must be relative to the file that actually required proxyquire, not to the currently executing test

In a lot of our tests we want to centralize test bootstrapping so we've put loading of proxyquire into a centralized bootstrap file. So in a given test file this ends up looking like this (coffeescript):

{proxyquire} = require '../helpers/bootstrap'

When doing this , all of my calls to proxyquire(...) need to have the path relative to the bootstrap.coffee file and not the test file.

To test this, I removed the requiring of proxyquire from the bootstrap file into the test file itself and paths worked as expected. I also moved the bootstrap file to a new directory and confirmed that I had to change all of my relative paths passed to the proxyquire call to be relative to the new bootstrap.

Any ideas as to why this might be happening or if there's a possible fix?

Globally override a module that returns a function

I know that you can set '@global': true in the stubs for modules that are objects, but how do you do it for modules that return functions. For example:

// main.js
var Deep = require('./deep');

var instance = new Deep();
instance.run();

module.exports = instance;
// deep.js
var deepest = require('./deepest')('My Name');

function Deep() {
}

Deep.prototype = {
  run: function() {
    deepest.baz();
  }
};

module.exports = new Deep();
// deepest.js
function Deepest(name) {
  return {
    baz: function() {
      console.log(name);
    }
  };
}

module.exports = Deepest;

Deepest returns a function that I need to mock out, but since it is used inside of Deep, I have to use @global.

If deepest was exporting the inner object instead of the wrapping function, I could do this:

var main = proxyquire('./main.js', {
  './deepest': {
    '@global': true,
    'baz: function() {}
  }
}

But since deepest returns a function, my understanding is that I have to mock it like this:

var main = proxyquire('./main.js', {
  './deepest': function() {
    return {
      baz: function() {
        console.log('mocked');
      }
    }
  }
}

But I can no longer set '@global' on the mock object. Right? How should I handle this? This situation has arisen because of the api design of a third party module so I sadly can't really restructure these calls.

Support for Webpack?

Hello,

Thanks for this great library! I wonder whether there are any plans to support also Webpack in addition to Browserify. How large job is it to add support for it?

Thank you!

failure of fakeStub for certain require modules when used in combination with blanketJS

proxyquire has an issue when combined with blanketJS

    var foo = proxyquire('foo', { 'path': pathStub }); //is ok
    var bar = proxyquire('./bar', { 'path': pathStub }); //not okay

the bar gets fully parsed into absolute path say "c:\node\website\xyz\lib\bar.js".

Cause:
I observed that this is happening as a result of require.extensions[extname] also being present in the blanketJS code base as require.extensions['js'].

the blanketJS is being loaded after the proxyquire and thus overrides the method signature.

Environment:

  • node 10 on Windows
  • mocha for testing
  • powered by grunt

Recursive Overrides

I'm working on a way of tracking what files various compilers (like CoffeeScript, Jade, and Stylus) rely on when compiling, to make a better asset-graph for roots. For example, if a Jade file has the line include _partial, when it is compiling it will read _partial.jade, and whenever _partial.jade is modified, the original Jade file will need to be recompiled.

In order to track what files get read by the compiler, I am trying to stub fs so that readFile() and readFileSync() log what files are read. However, these compilers are made up of several modules, so I need a way to override fs throughout the entire compiler, without knowing any of the names of the compiler modules (since we aim to support ~30 languages, it wouldn't be easy to study each compiler).

Do you have any idea on how to do this?

Proxyquire seems to break stack traces

I'm trying to mock the chalk module for ESLint tests to be able to test the stylish formatter:
https://github.com/eslint/eslint/blob/master/lib/formatters/stylish.js
Unfortunately, this seems to break stack traces which makes it harder to find where the problem is. I'm mocking chalk red & yellow methods via:

var chalkStub = Object.create(chalk),
    counters = {};

["yellow", "red"].forEach(function (color) {
    counters[color] = {
        regular: 0,
        bold: 0
    };
    Object.defineProperty(chalkStub, color, {
        value: function (str) {
            console.log("trace for color", color);
            console.trace();
            console.log("");
            var colored = chalk[color](str);
            counters[color].regular++;
            return colored;
        },
        writable: true
    });
    chalkStub[color].bold = function (str) {
        console.log("trace for bold color", color);
        console.trace();
        console.log("");
        var colored = chalk[color].bold(str);
        counters[color].bold++;
        return colored;
    };
});

var formatter = proxyquire("../../../lib/formatters/stylish", {chalk: chalkStub});

In a different part of the file, I have:

var result = formatter(code, config);

This should invoke the stylish formatter & show me what exactly led to invocation of the yellow method but I get this trace instead:

trace for bold color yellow
Trace
    at Function.chalkStub.(anonymous function).bold (/Users/mgol/Documents/projects/public/eslint/tests/lib/formatters/stylish.js:35:17)
    at module.exports (/Users/mgol/Documents/projects/public/eslint/lib/formatters/stylish.js:9:3011)
    at Context.<anonymous> (/Users/mgol/Documents/projects/public/eslint/tests/lib/formatters/stylish.js:72:26)
    at Test.Runnable.run (/Users/mgol/Documents/projects/public/eslint/node_modules/mocha/lib/runnable.js:211:32)
    at Runner.runTest (/Users/mgol/Documents/projects/public/eslint/node_modules/mocha/lib/runner.js:358:10)
    at /Users/mgol/Documents/projects/public/eslint/node_modules/mocha/lib/runner.js:404:12
    at next (/Users/mgol/Documents/projects/public/eslint/node_modules/mocha/lib/runner.js:284:14)
    at /Users/mgol/Documents/projects/public/eslint/node_modules/mocha/lib/runner.js:293:7
    at next (/Users/mgol/Documents/projects/public/eslint/node_modules/mocha/lib/runner.js:237:23)
    at Object._onImmediate (/Users/mgol/Documents/projects/public/eslint/node_modules/mocha/lib/runner.js:261:5)
    at processImmediate [as _immediateCallback] (timers.js:336:15)

The line:

    at Context.<anonymous> (/Users/mgol/Documents/projects/public/eslint/tests/lib/formatters/stylish.js:72:26)

points to the place where I invoke:

var result = formatter(code, config);

the line:

    at module.exports (/Users/mgol/Documents/projects/public/eslint/lib/formatters/stylish.js:9:3011)

is the only reference to the reporter file. The line no. 9 is empty in this file and the invocation must be happening way lower in the file but I have no way to get this information from the trace.

Cyclic Dependencies

I am running into an issue that probably many ppl have who use express along with proxyquire, since express projects usually have a cyclic dependency in their setup. But this issue could really occur in any project with 2 files requiring each other. For demonstration purposes, I gonna sketch out an example with express (sorry for making this so verbatim and if I go through some very basic express setup here):

Express projects usually have an app.js at the top of the dependency chain that registers some middleware and the routes the server should listen to. Usually ppl attach all their routes in a different file to keep the app.js short.

// app.js
const app = module.exports = express()
const server = http.createServer(app)

// ... here go some pre-routing middleware
require('./routes/webroutes')
// ... then some post-routing middleware

// finally the server is started
server.listen()

The webroutes.js simply requires the app.js singleton and attaches some routes to it. Note that at the point of time at which webroutes.js executes app.js is not fully configured yet (in fact, only the first line of app.js has been executed yet).

// routes/webroutes.js
var app = require('../app)
app.get('/v0-1-0/hello/world', helloController.sayWorld)

To complete the picture, here the controller that depends on modules I would like to sub out, fs for example.

// controllers/helloController.js
var fs = require('fs')
exports.sayWorld = function() {
  return fs.mkdirSync('/hello/world')
}

I now would like to create a functional test that starts the server in its entirety. The only way I can get this sort-of working is this:

// test/app.js
var stubbedHelloController = proxyquire('../routes/webroutes', {
  'fs': myFsStub
})

// get a stubbed app and prevent that the unstubbed app instance gets any routes attached
var stubbedApp = proxyquire('../app', {
  './routes/webroutes': {}
})

// then attach the routes to the stubbed app
var subbedWebroute = proxyquire('../routes/webroutes', {
  '../app': stubbedApp,
  '../controllers/helloController': stubbedHelloController
})

This really feels like a hack and there are other cyclic dependencies that cannot be bypassed like this. In the above example, the routes are registered after the post-routing middleware. My question is, is there any way to handle cyclic dependencies properly? Global mocking as suggested in issue #12 might resolve this issue as long as one of the participating modules in the cycle are not the ones you wanna mock. Any suggestions?

Example with express+selenium

Hi,

I got referred to proxyquire by Steve Cresswell, the guy behind BDD framework Yadda.

I'm liking the look of proxyquire.

As a relative noobie to Javascript and nodejs/express - I'm hoping for a leg up with an example of using proxyquire with express+node+selenium to use with my Yadda tests.

I'm struggling to see how we can bootstrap the fake within this environment.

The web page is calling into the route in express, I don't want to fake the route code, that still needs to execute. The route code calls a service and I want to fake an error coming out of the service call.

Cheers,

Nick

Cant proxy when path is variable

I'm using a variable (__BASE) for the root directory but seems like its not working.

Is there an easy fix for that?

that's working great:

proxiedLocation = proxyquire(`${__BASE}/app/adapters/location`,{
    '../services/location': locationService
 });

but when I'm changing the '../services/location' to __BASE + /app/services/location or SERVICE_LOCATON_PATH or the es6 syntax its not working.

Thanks.

Proxyquire Failing to load stubbed content

Hi,

I really like using proxy quire but I have been running into a strange issue. When i stub a required object, the original is loaded. If i npm remove the object it throws 'Cannot find module'. So i created the smallest use case for this.

File: demo.js

var _ = require('lodash');

module.exports.test1 = function() {
  return _.sum([1, 2]);
};

var doesNotExist = require('doesNotExist');

module.exports.test2 = function() {
  return doesNotExist.test();
};

Test Case: demo.spec.js

var proxyquire = require('proxyquire'),
  chai = require('chai'),
  expect = chai.expect;

function setup() {
  return proxyquire('./demo', {
    lodash: {
      sum: function(arr) {
        var total = 0;
        arr.forEach(function(num) {
          total += num;
        });
        return total + 'test';
      }
    },
    doesNotExist: {
      test: function() {
        return true;
      }
    }
  })
}

describe('Test Proxyquire', function() {
  it('should handle lodash override correctly', function() {
    var test = setup();
    expect(test.test1([1, 2])).to.be.equal('3test')
  });

  it('should handle doesNotExist correctly', function() {
    var test = setup();
    expect(test.test2()).to.be.equal('proxy worked');
  });
});

run

npm install mocha lodash chai proxyquire

launch test with

node node_modules/mocha/bin/_mocha --reporter spec demo.spec.js

The first test will pass if you remove the 'var doesNotExist = require('doesNotExist');' line. However proxyquire doesn't seem to be able to override a module that isn't installed.

Is this the intended functionality? Did I miss some documentation?

Problems mocking fs module

I use proxyquire a lot while testing and all is working fine, except when I try to mock the fs module. The shortest example:

var fsStub, proxyquire, subject;
proxyquire = require('proxyquire');
fsStub = null;

subject = proxyquire('./lib/worker/update', {
  fs: fsStub
});

Leads to:

/private/tmp/t/node_modules/proxyquire/lib/proxyquire.js:147
      throw moduleNotFoundError(path);
            ^
Error: Cannot find module 'fs'
    at createNotFoundError (/private/tmp/t/node_modules/proxyquire/node_modules/module-not-found-error/index.js:4:13)
    at Proxyquire._require (/private/tmp/t/node_modules/proxyquire/lib/proxyquire.js:147:13)
    at require (module.js:384:17)
    at Object.<anonymous> (/private/tmp/t/lib/worker/update.js:1:72)
    at Module._compile (module.js:460:26)
    at Object.Module._extensions..js (module.js:478:10)
    at Object.require.extensions.(anonymous function) [as .js] (/private/tmp/t/node_modules/proxyquire/lib/proxyquire.js:243:43)
    at Module.load (module.js:355:32)
    at Function.Module._load (module.js:310:12)
    at Module.require (module.js:365:17)

Am I missing something here?

proxyquire: v1.7.1
nodejs: v0.12.7

Add documentation: Only works on functions

I've run into situations where I want to modify the global config object (which is basically just json). Proxyquire seems like an excellent tool for this, but after much trial and error I've come to the (correct?) conclusion that this module is only designed to work on replacing functions that are dependencies of a module, not values. It might be helpful to document proxyquire doesn't change values for other wayward developers like myself (or maybe I'm alone in wanting to do this).

For posterity's sake, in node v0.10.x, you can modify values thusly:

require('your-module').value = 'STUB VALUE';

It looks odd, but it seems to work for me.

Special handling for transpiled ES6 modules?

Currently, if you want to stub a transpiled es6 module, you need to do something like this:

const mod = proxyquire('./path/to/mod', {
  '../dep': {
    __esModule: true,
    doSomething: function() { /* ... */ },
  },
});

The __esModule is used by tools like Babel and Traceur to deal with module format interop. It would be convenient if proxyquire automatically added it to the stub if present in the original.

undefined hasOwnProperty?

I'm a little baffled by this one, because hasOwnProperty is a part of node core. Using node-v0.12.7 and proxyquire-1.6.0.

/Users/kevin/Projects/omnisearch/node_modules/proxyquire/lib/proxyquire.js:117
    if (hasOwnProperty.call(stubs[key], '@global')) {
                       ^
TypeError: Cannot convert undefined or null to object
    at hasOwnProperty (native)
    at Proxyquire.load (/Users/kevin/Projects/omnisearch/node_modules/proxyquire/lib/proxyquire.js:117:24)

How to stub out the filesystem many modules deep

I'm trying to use fe to run jasmine on my browserified code:

var jasmine = proxyquire('gulp-jasmine', { 'fs': fe.fs })

gulp.src('./test/*')                                                                 
  .pipe(browserify(...))                                                                                  
  .pipe(                                                                             
    es.map(function (file, callback) {                                               
      var folder = fe.instance().directory(path.dirname(file.path))                  
      fe.instance().file(folder, path.basename(file.path))                           
      callback(null, file)                                                           
    })                                                                               
  )                                                                                  
  .pipe(jasmine())                                                                                  

But jasmine still tests the unbrowserified code! It seems like proxyquire is only replacing fs one level deep. I need everything that gulp-jasmine requires to also use the stubbed fs module.

Proxyquire will not stub falsey value

requireStubs = {
            './models/recacheModel': modelMock,
            './server': serverStub,
            'config': {
                'recache': {
                    'auto': true,
                    'interval': 50
                },
                'nodeTime': false //does not work with null either
            }
        };         
        var fileUnderTest = proxyquire(loadPath + 'startServer.js', requireStubs);
var nodeTimeConfig = require('config').nodeTime;
if(nodeTimeConfig){
    require('nodetime') //blows up
}

In this particular case I worked around this by changing my config setup, but being able to stub something falsey would be a nice feature.

This would probably require some kind of hack/convention other than just property: false because of the way objects work

Global overrides

This was touched on in #22 and #16, but would it be possible for proxyquire to override require globally rather than only one level deep?

The API could look similar to no-call-through:

var foo = proxyquire('./foo', {
  path: {
      extname: function (file) { ... }
    , '@noCallThru': true
    , '@global': true  //  <-- Makes this override apply everywhere
  }
});

My use case is a little outside of proxyquire's usual remit. I'm writing a workshopper based tutorial where the user submits a solution, A, to a problem. A requires B which requires C, but the interactions with C are what dictates whether the solution is correct or not.

I proxyquire the solution with stubs for C, so if it were to override require globally then asserting on the correct interactions becomes really simple.

Does not work with strict mode modules

Due to use of caller, any modules that have "use strict" at the top and call the proxied require will immediately break.

It looks like you need the caller's __dirname in order to resolve relative modules. I think there are a variety of ways to do this, perhaps involving require.resolve, require.cache, module.parent, or some combination thereof.

You mentioned on Twitter stripping the strict mode for proxyquire "because it is only used for testing." That's not correct; strict mode has runtime semantic changes that are important to preserve (e.g. better exceptions, different eval behavior, no implicit global this).

Enhancement

Hey,

I've been giving it a good bit of thought and I think I can squash the global issue without breaking compatibility and without forcing users to use noPreserveCache. I'm sure those methods are still helpful for other edge cases that we haven't thought of, but please consider this solution.

Current

  try {
    return this._parent.require(request);
  } finally {
    if (self._preserveCache) {
      if (cached)
        Module._cache[id] = cached;
      else
        delete Module._cache[id];

      if (ext_super)
        require.extensions[extname] = ext_super;
    }
    else
      delete require.cache[id];
  }

New

  try {
    return this._parent.require(request);
  } finally {
    if (self._preserveCache) {
      // Clear the stubbed cache
      delete require.cache[id];

      // Re-read the module to restore the globals without stubs
      require(request);   

      // Continue restoring the original module as before for state and Singletons
      if (cached)
        Module._cache[id] = cached;
      else
        delete Module._cache[id];

      if (ext_super)
        require.extensions[extname] = ext_super;
    }
    else
      delete require.cache[id];
  }

I'm really leaning towards a PR for this. Of course, at that point, I'm not sure what I'd end up putting in the wiki.

Doesn't seem to be overriding require?

I am not sure what is going on but I have been trying multiple mocking/require hijacking libraries to see if I can mock some of my dependencies. I like proxyquire but the problem being proxyquire doesn't seem to be giving me my mocked objects.

// item.js
var parser = require('./parser');

module.exports = {
  someFunctionThatUsesParser: function(){ ... };
}
// item-spec.js
var proxy = require("proxyquire"),
  item;
//jasmine before each
beforeEach(function(){
  var mock = {
    'parser' : {
      myMockedFunction: function(){ ... }
    }
  };
  item = proxy("../src/item", mock);
});
// tests below

Folder structure is:

project/
  |- src/
  |--- item.js
  |--- parser.js
  |- spec/
  |--- item-spec.js

Is that not the way this is supposed to be set up? I have checked to see if the parser object that item uses vs what I have mocked are the same object and they are not. Any Ideas?

A way to fake require.resolve function

To start I want to say its an excellent module. Thanks for the great work.

Now I do use proxyquire to fake certain modules, that works great. But in my application i use the function require.resolve function to get the path of the dependency but I am not able to fake it.

Example code:

function getPlugin(pluginName){
    var plugin = require(pluginName);
    var pluginPath = require.resolve(pluginName); // ---> Error here

    return {
        api: plugin,
        path: pluginPath
    };
}

Since I use proxyquire so require works but it throws an error on line 3.

Browserify Compatibility

We're using browserify to share our server side code with the client.
Our unit tests heavily use proxyquire to mock out module dependencies.

Of course we'd like to also run our unit tests in browsers, to make sure everything is working correctly. When attempting to browserify the unit tests and run them in the client, I ran into issues related to require.cache and require.resolve in https://github.com/thlorenz/proxyquire/blob/master/index.js#L7 since they are undefined.
I'd really like to get this working, so I'm wondering what needs to be done to make proxyquire compatible with browserify. Since you're quite active in the browserify project, maybe you already have an idea, or can immediately tell me it's not possible.

I'd love to help out with this.

Relative paths for sub-modules?

Hi, I have an use case where I define some routes directly in a routing.js file, and some other routes are defined by another package. This other package uses path.resolve(modulepath) and then requires that. I've tried a lot of different things, but I wasn't able to figure out what path I should use so that proxyquire is able to mock those.

The use case would be testing that the other package effectively does call app[verb] with the correct endpoint and middleware.

Is there some way I could debug this? Say, does proxyquire have the ability to tell me what modules are required and what paths were used in those require statements, so that I can mock them?

Possible to stub constructors?

For example-

In my 'email.js' I have:

var mandrill = require('mandrill-api/mandrill');
var mandrill_client = new mandrill.Mandrill('API_KEY_HERE');

exports.sendTemplate = function(templateName, to, variables, callback) {

    console.log('mandrill_client === ', mandrill_client)

    var message = {
        //omitted for brevity
    };

    mandrill_client.messages.sendTemplate({
        template_name: templateName,
        template_content: [],
        message: message,
    }, function(result) {
        //... do something
        return callback();
    }, function(err) {
        //...
    });
}

Then, in my test, I want to stub out mandrill, so that when a new mandrill_client is created, it gets my stubbed version, ultimately with a sinon.spy on mandrill_client.messages.sendTemplate

//not sure what mandrillStub should be??

email = proxyquire('../../../app/helpers/email', {
    'mandrill-api/mandrill': mandrillStub
});

Is this possible?

Stub not overriding original

Hi,

I realize I'm probably doing something wrong, but I've tried several things and no matter what I do I can't get my stubbed function to run within my module under test. I have no problems when experimenting with variations of provided samples including the sinon one. I'm hoping a more experienced pair of eyes could help me out a little.

Module under test with nano, the couchdb module dependency I want to mock.

var async = require('async');
var db = require('nano')('http://localhost:5984/mydb');

module.exports.getDocs = function(docs, callback){
  // some logic
  async.map(docs, function(doc, cb) {
    db.get(doc, function(err, body) {
      cb(err, body);
    });
  }, function(err, results) {
    if (err) {
      callback(err, null);
    } else {
      callback(null, results);
    }
  });
};

Test using proxyquire and sinon.

var proxyquire = require('proxyquire');
var sinon = require('sinon');
var db = require('nano')('http://localhost:5984/mydb');
var couchdb; // import using proxy below

describe('CouchDB document model', function(){
  var getStub;

  before(function () {
    getStub = sinon.stub(db, 'get');
    couchdb = proxyquire('../../../app/models/couchdb', { db: {get: getStub} });
    getStub.yields({'some': 'data'});
  });

  after(function () {
    db.get.restore();
  });

  describe('getDocs function', function(){
    it('should use fake couchdb data', function(done) {
      couchdb.getDocs(docs, function(err, body) {
        // Getting body with data from real CouchDB, i.e. original db.get is called
        done();
      });
    });
  });

});

noPreserveCache doesn't seem to work in 1.0.0

Somewhere between 0.6.0 and 1.0.0, the noPreserveCache function no longer appears to be doing what the documentation says it will do.

I have a situation similar to the one described in #25โ€” Imagine I have the following files:

foo.js:

exports.bar = function() {
  return 'real';
};

usesFoo.js:

var foo = require('foo');
exports.baz = function() {
  return foo.bar() + ' thing';
};

usesFooUnitTest.js:

var proxyquire = require('proxyquire').noPreserveCache();
var usesFoo = proxyquire('usesFoo', {
  'foo': {
    bar: function() {
      return 'fake';
    }
  }
});
expect(usesFoo.baz()).to.equal('fake thing'); // test passes

integrationTest.js:

var usesFoo = require('usesFoo');
expect(usesFoo.baz()).to.equal('real thing'); // test fails! returns 'fake thing'

Since I have a grunt build that runs unit tests immediately followed by integration tests, my build fails on the integration tests as shown above. If I just run integration tests in isolation, they pass just fine. Also, if I change my package.json to use proxyquire 0.6.0, my build also passes.

Obviously understanding that any 0.x.x version may not yet have a hardened API... I'm wondering: was this an intended breaking change when moving to 1.0, and the documentation is just out of date? Or is this a regression? If it's the latter, is there a suggested workaround?

Thanks!

Impossible to stub non-existing module expecting to return a function.

Hi, I have a factory that I wish to test some functionality of.

This factory method returns new function() instances.

Therefore I wish to stub something along the line of:

proxyquire('factorypath': {
'factorypath/testFunc' : testFunc
});

But it won't allow it. So I thought I'd set '@noCallThru', but that is not possible when a module is supposed to return just a function.

Or am I missing something here?

How to reset/un-mock the mocked dependency in proxyquire?

File structure:

.
|____lib
| |____bar.js
| |____baz.js
| |____foo.js
|____test
| |____bar.js
| |____baz.js
| |____foo.js

Use case:

With respect to the above file structure, ./lib/foo.js requires ./lib/bar.js, ./lib/bar.js requires ./lib/baz.js.


While unit testing ./lib/foo.js via ./test/foo.js, I would like to mock ./lib/bar.js, so that, I am only concerned with ./lib/foo.js.
Once the tests in ./test/foo.js are over I would like to reset/un-mock ./lib/bar.js.

While unit testing ./lib/bar.js via ./test/bar.js, I would like to mock ./lib/baz.js, so that, I am only concerned with ./lib/baz.js.
Once the tests in ./test/foo.js are over I would like to reset/un-mock ./lib/baz.js.

So on and so forth.


Or in other words, I would like to mock the dependencies and reset as and when required, in the test file.

Most likely mocking several times in the test file and reseting a after all the test are over in a test file.

Or may be I can control the local mock, with some file level closure variables


Looks like mockery addresses my use-case, mainly reset/un-mock the mocked dependency.

How to achieve the same in proxyquire?

Windows 7 not supported

Hey, great work - this is (almost) exactly what I needed for my tests :)
Unfortunately though i tend to develop on multiple platforms including windows 7. When I try to use proxyquire on windows I get the following error:

    Error: Cannot find module 'V:GitHubTestRunner
ode_modulesproxyquireproxyquire.js'
      at Function.Module._resolveFilename (module.js:338:15)
      at Function.Module._load (module.js:280:25)
      at Module.require (module.js:362:17)
      at require (C:\Users\PHALLI~1\AppData\Local\Temp\mocha.js@0:1:211)
      at new module.exports (C:\Users\PHALLI~1\AppData\Local\Temp\mocha.js@0:2:15)
      at Context.<anonymous> (V:\GitHub\TestRunner\test\grunt\mocha.test.js:23:19)
      at Test.Runnable.run (V:\GitHub\TestRunner\node_modules\mocha\lib\runnable.js:187:15)
      at Runner.runTest (V:\GitHub\TestRunner\node_modules\mocha\lib\runner.js:307:10)
      at Runner.runTests.next (V:\GitHub\TestRunner\node_modules\mocha\lib\runner.js:353:12)
      at next (V:\GitHub\TestRunner\node_modules\mocha\lib\runner.js:235:14)

from a call like this:

    var MochaTask = proxyquire.resolve('../../src/grunt/mocha.js', __dirname, {
            'mocha': mochaMock(),
            'module': new ModuleMock()
        });

looks like it is munging the path separators.

BTW, using proxyquire 0.3.2

Proxyquire cannot stub non-object imports

Say I have a module options.coffee...

module.exports = 'foo'

I want to stub it for a test...

describe '/lib/anotherModule', ->
  imports = {}
  before ->
    imports['./options'] = 'bar'
  beforeEach ->
    thing = proxyquire "#{process.cwd()}/lib/thing", imports
  it 'should be defined', ->
    thing.should.exist

This will fail in the before block, because Proxyquire cannot mock non-object exports. The error is:

    TypeError: Object.keys called on non-object
    at Function.keys (native)
    at fillMissingKeys (/Users/pete/kinvey/projects/cli/node_modules/proxyquire/lib/proxyquire.js:12:10)
    at Proxyquire._require (/Users/pete/kinvey/projects/cli/node_modules/proxyquire/lib/proxyquire.js:143:7)
    at require (module.js:380:17)

Feature Request: Prevent proxyquire from failing if it is being used to mock a .json require

if proxyquire is used to mock a .json file that is loaded in through require, i wonder if it would be better behavior if it was possible for it to not require the real .json file to exist so proxyquire could just operate off the mock solely my main example is config management say for example your writing tests around your configmanager that relies on an env.config file on all your deployment machines, but not necessarily on all the dev boxes, i would like the ability to run the tests for the configmanager without needing the env.json file to exist and instead catch and return the stubbed object defined in proxyquire.resolve without proxyquire trying to resolve the original path provided.

Support for node-webkit?

We have a node-webkit app, that has angularjs services and we 'require' node modules inside them. These files do not have any module.exports. We are writing unit test cases and we want to mock the require's present in these files. Any plan to support this case in future?

Thanks

proxyquire won't catch dynamic requires

It's as if proxyquire won't stay active to catch later requires, or it is designed like that because it can't handle those.

I surely hope to get an explanation :)

Is it possible to assert that what I proxyquired was actually required?

// foo-test.js
var proxyquire = require('proxyquire');
var foo = proxyquire('../foo', {'../bar: {}});

assert(proxyquire.wasProxied('../bar'));

Can I do something along these lines in order to ensure that my ../bar path hasn't changed since I stubbed the file? This would be helpful for a constantly changing codebase in case the stubbed file moves and then is no longer stubbed.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.