diff --git a/README.md b/README.md index 15742af..65844bc 100644 --- a/README.md +++ b/README.md @@ -127,6 +127,41 @@ Two simple steps to override require in your tests: - 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 +## Throw if proxyquire tries to load a stub that does not exist + +By default `proxyquire` will stub out modulePaths, whatever their path may be. +This includes if a dependency is not accessible (wrong file path) or not installed and accessible. + +To raise an error if `proxyquire` attempts to load a module that does not exist, +you can utilize the *throwOnNotFound* function. + +**Without throwOnNotFound:** +```javascript +proxyquire('./foo', { + 'doesNotExist': () => {} +}); +``` + +The above code snippet will not raise any errors. + +**With throwOnNotFound:** +```javascript +var proxyquireThrowOnNotFound = require('proxyquire').throwOnNotFound(); + +proxyquireThrowOnNotFound('./foo', { + 'doesNotExist': () => {} +}); +``` + +This will throw an error when your tests run letting you know that proxyquire +cannot find `doesNotExist`. Typically, this is occurs when a file was renamed +in the calling module but was not updated in the proxyquire definition in the +test. + +This method is also chainable with the *callThru* methods: + +`var proxyquireThrowOnNotFoundAndNoCallThru = proxyquire.throwOnNotFound().noCallThru()` + ## 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. diff --git a/lib/proxyquire.js b/lib/proxyquire.js index a169c38..35702f3 100644 --- a/lib/proxyquire.js +++ b/lib/proxyquire.js @@ -96,6 +96,19 @@ Proxyquire.prototype.preserveCache = function () { return this.fn } +/** + * Stubbing a module that does not exist (from the perspective of the proxyquire + * subject) will throw an error. + * @name throwOnNotFound + * @function + * @private + * @return {object} The proxyquire function to allow chaining + */ +Proxyquire.prototype.throwOnNotFound = function () { + this._throwOnNotFound = true + return this.fn +} + /** * Loads a module using the given stubs instead of their normally resolved required modules. * @param request The requirable module path to load. @@ -140,6 +153,10 @@ Proxyquire.prototype._resolveModule = function (baseModule, pathToResolve) { paths: Module.globalPaths }) } catch (err) { + if (this._throwOnNotFound) { + throw new ProxyquireError(err.message) + } + // If this is not a relative path (e.g. "foo" as opposed to "./foo"), and // we couldn't resolve it, then we just let the path through unchanged. // It's safe to do this, because if two different modules require "foo", diff --git a/test/proxyquire-argumentvalidation.js b/test/proxyquire-argumentvalidation.js index 4b618c9..23f1cbd 100644 --- a/test/proxyquire-argumentvalidation.js +++ b/test/proxyquire-argumentvalidation.js @@ -63,4 +63,17 @@ describe('Illegal parameters to resolve give meaningful errors', function () { throws(act, /Invalid stub: "myStub" cannot be undefined/) }) }) + + describe('when I pass a stub with a key that is not required on the proxyquired object', function () { + function act () { + proxyquire.throwOnNotFound() + proxyquire('./samples/foo', { + nonExistent: () => {} + }) + } + + it('throws an exception with the stub key', function () { + throws(act, /Cannot find module 'nonExistent'/) + }) + }) })