Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

testdouble

Package Overview
Dependencies
Maintainers
2
Versions
115
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

testdouble - npm Package Compare versions

Comparing version 1.0.0 to 1.1.0

generated/test/lib/replace/index-test.js

4

docs/4-creating-test-doubles.md

@@ -7,3 +7,3 @@ # Creating Test Doubles

## testdouble.function([name])
## td.function([name])

@@ -24,3 +24,3 @@ To create a fake function with test double, we use the `function` function. At its simplest, invoking:

## testdouble.object()
## td.object()

@@ -27,0 +27,0 @@ Creating a one-off function is really easy, but often our subjects will depend on objects with functions as properties. Because we don't want to encourage the use of [partial mocks](https://github.com/testdouble/contributing-tests/wiki/Partial-Mock), test double offers a number of ways to create objects whose function properties have all been replaced with fake functions.

@@ -5,7 +5,7 @@ # Stubbing behavior

In testdouble.js, we stub behavior with the `testdouble.when()` function. In this chapter, we'll discuss simple stubbings, matching inexact arguments, and advanced configuration options that testdouble.js supports.
In testdouble.js, we stub behavior with the `td.when()` function. In this chapter, we'll discuss simple stubbings, matching inexact arguments, and advanced configuration options that testdouble.js supports.
All of the examples in this document presume the reader has aliased `testdouble` to `td`.
## testdouble.when()
## td.when()

@@ -137,3 +137,3 @@ The basic structure of a stubbing configuration follows:

#### testdouble.matchers.anything()
#### td.matchers.anything()

@@ -153,3 +153,3 @@ When passed `td.matchers.anything()`, any invocation of that test double function will ignore that parameter when determining whether an invocation satisfies the stubbing. For example:

#### testdouble.matchers.isA()
#### td.matchers.isA()

@@ -170,3 +170,3 @@ When passed `td.matchers.isA(someType)`, then invocations of the test double function will satisfy the stubbing when the actual type matches what is passed to `isA`. For example:

#### testdouble.matchers.contains()
#### td.matchers.contains()

@@ -231,3 +231,3 @@ When passed `td.matchers.contains()`, then a stubbed argument can be loosened to be satisfied by any invocations that simply contain the portion of the argument. This works for several types, including strings, arrays, and objects.

#### testdouble.matchers.argThat()
#### td.matchers.argThat()

@@ -234,0 +234,0 @@ If the other built-in matchers don't serve your needs and you don't want to roll

@@ -31,3 +31,3 @@ # Verifying interactions

## testdouble.verify()
## td.verify()

@@ -89,3 +89,3 @@ A basic verification looks like this:

#### testdouble.matchers.anything()
#### td.matchers.anything()

@@ -106,3 +106,3 @@ The `anything()` matcher will only ensure that an argument was passed, but will

#### testdouble.matchers.isA()
#### td.matchers.isA()

@@ -127,3 +127,3 @@ The `isA()` matcher can be used to verify a matching type for a given argument.

#### testdouble.matchers.contains()
#### td.matchers.contains()

@@ -173,3 +173,3 @@ The contains matcher is satisified if the passed-in portion of a string, array,

#### testdouble.matchers.argThat()
#### td.matchers.argThat()

@@ -176,0 +176,0 @@ When the argument match needed is more complex than can be described above, one

@@ -1,30 +0,46 @@

# Replacing Dependencies with Test Doubles
# Replacing Real Dependencies with Test Doubles
All of these test doubles aren't of much value if your subject can't reference
them. Because CommonJS module-loading with `require` is the dominant way to
organize and load code across file listings, testdouble.js provides a special
mechanism for replacing particular file paths with test doubles in as unobtrusive
a way as possible.
them, so testdouble.js provides some conveniences to swapping out your subject's
real dependencies for fake ones with its `td.replace` function.
This document assumes `testdouble` is aliased to `td`.
At present, `td.replace` provides two mechanisms for providing test doubles to
your test subject:
## Node.js
* **Object-property replacement.** By passing
`td.replace(someObject, 'nameOfProperty')`, testdouble.js will retain a reference
to `someObject.nameOfProperty`, and replace it during your test
* **Node.js module replacement.** By passing
`td.replace('../path/to/dependency')`, testdouble.js will intercept calls to
`require` that `dependency` module and ensure your subject is handed a fake
instead (requires Node.js 0.11 or greater)
> **Note:** this feature will not work on Node.js 0.10 or earlier, meaning it
requires Node.js 0.11 or later (or any iojs release).
In both cases, `td.replace` will grab the real dependency and imitate it with an
appropriate fake:
To make it as easy and clear as possible to replace a subject's real dependencies
with test doubles, testdouble.js provides an intelligent `replace()` function,
powered by a module named [quibble](https://github.com/testdouble/quibble). By
calling `td.replace('../some/path/to/a/dependency')`, any subsequent calls to
`require` for paths that resolve to the same absolute path will be intercepted
and replaced with a test double function or object by mirroring whatever the
actual dependency exports when `require`'d.
* Plain functions are replaced with test double functions of the same name
* Plain objects are shallow-cloned and their top-level functions are replaced
with test double functions
* Constructor functions with at least one prototypal function defined will
_return_ a plain object of test double functions but will be _replaced by_ an
artificial constructor that, when instantiated, will delegate to those same
test double functions
It sounds a little like magic, so let's look at a simple example. Suppose we
After the next call to `td.reset()` (which you should have in an `afterEach` hook
somewhere in your test suite), the real dependencies will all be restored.
If the imitation scheme doesn't suit you or if you don't want your test to drive
out the plumbing of defining the dependency, you can pass a final argument to
`td.replace` that will act as the fake that replaces the real dependency (e.g.
`td.replace('./foo', 42)` will monkey-patch `require` to return `42` for paths
that resolve to that absolute path.
## Node.js
This sounds a little like magic, so let's look at a simple example. Suppose we
write a simple test in `test/lib/car-test.js`:
``` javascript
var brake = td.replace('./../../lib/brake'),
subject = require('./../../lib/car')
var brake = td.replace('../../lib/brake'),
subject = require('../../lib/car')

@@ -38,3 +54,3 @@ subject.slowDown()

export a function, so that testdouble.js knows to replace `require` calls with
a test double function (as opposed to an empty `module.exports` object):
a test double function (as opposed to a default `module.exports` object):

@@ -56,166 +72,103 @@ ``` javascript

The API above is unusual enough that we recommend you poke around at [the more
involved example project](../examples/node/test/lib/car-test.js) provided into
the testdouble.js repository. For a more formal discussion of the `replace()`
As you can see, each file listing references the correct relative paths to the
replaced dependency. From the perspective of the test, the `brake` module is in
`'../../lib/brake'`, but from the perspective of the subject, `brake` is in
`'./brake'`.
If you'd like to kick the tires on this, you can play with a [more involved
example project](../examples/node/test/lib/car-test.js) found in the
testdouble.js repository. For a more formal discussion of the `replace()`
API, read on.
### testdouble.replace(relativePath, [fakeToReplace])
### Aside: third-party modules
Pass `replace()` a relative path string as if the test was calling `require` for
If you're curious why testdouble.js doesn't support replacing third-party
modules, you can see our commentary on why we "[don't mock what we don't
own](B-frequently-asked-questions.md#why-doesnt-tdreplace-work-with-external-commonjs-modules)".
the dependency to be replaced with a test double. Calling `replace` will:
## Browser
1. Resolve the provided relative path to an absolute one
2. Call `require` on the path to see whether its module exports a plain function,
a plain object containing function properties, or a constructor function (as
determined by having functions on the `prototype` object)
3. Create a test double function, object, or artificial constructor whose
functions have been replaced by test doubles, respectively
4. Wrap the Node.js built-in `Module._load` function and intercept any calls made
to the dependency by the subject, instead returning the test double
5. Return the test double created in step 3 so the test has access to it
Given the eclectic array of browser JS namespacing, module loading, and packaging
schemes (not to mention the limited runtime introspection available to ES
`import` statements), testdouble.js doesn't try solve for every front-end module
and packaging scheme. For many projects, the object-property replacement scheme
will be good enough. For many others, `td.replace` could be used in a test helper
function to patch module schemes like AMD.
It is **very important** when using this feature that [`td.reset()` is invoked
after each test](1-installation.md#resetting-state-between-test-runs), or else
bizarre and terrible things will happen.
Using global-variable namespacing to carry forward our simple example above, we
could write this test:
#### replacing a module that exports a plain function
Let's say your subject is `lib/basket.js` and it depends on `lib/banana.js` and
your test is in a `test/lib` directory. If `banana.js` exported:
``` javascript
module.exports = function(){}
```
var brake = td.replace(app, 'brake')
subject = app.car
Then a test of `basket.js` would be able to use `td.replace()` to create and
inject a test double function named "lib/banana.js"
subject.slowDown()
``` javascript
var banana = td.replace('../banana'),
subject = require('../basket')
td.when(banana()).thenReturn('peel') // where banana is a test double function
td.verify(brake(10))
```
And if `basket.js` calls `require('./banana')`, it will receive the same `banana`
function returned to the test.
First, the test will fail until we define `app.brake` as a function:
#### replacing a module that exports a plain object
Given our subject is still `lib/basket.js` and it depends on `lib/fruits.js` and
your test is in a `test/lib` directory. If `fruits.js` exported:
``` javascript
module.exports.cherry = function(){}
module.exports.lime = function(){}
module.exports.lemon = function(){}
``` js
app.brake = function(){}
```
Then a test of `basket.js` would be able to use `td.replace()` to create and
inject an object of test double functions with names like "lib/fruits.js.lime"
Now we can write the function to make the test pass:
``` javascript
var fruits = td.replace('../fruits'),
subject = require('../basket')
td.when(fruits.lime()).thenReturn('juice') // where fruits.lime is a test double function
```
And if `basket.js` calls `require('./fruits')`, it will receive the same `fruits`
object returned to the test.
#### replacing a module that exports a constructor function
Sticking with our subject `lib/basket.js`, say it depends on `lib/juicer.js` and
your test is still in a `test/lib` directory. If `juicer.js` exported:
``` javascript
module.exports = function Juicer(){}
module.exports.prototype.juice = function(){}
```
Then a test of `basket.js` would be able to use `td.replace()` to create and
inject a wrapped constructor function imitating `Juicer`.
``` javascript
var juicer = td.replace('../juicer'),
subject = require('../basket')
subject()
td.verify(juicer.juice()) // where juicer.juice is a test double function
```
There's a subtle asymmetry in this case, however, because it's not enough to
inject an _instance_ of the `Juicer` function type, the subject needs to be able
to instantiate `Juicer` with `new` itself. The test doesn't have any particular
need to call `new Juicer()`, however, so it's returned a plain object containing
the test double functions.
That means that `lib/basket.js` would be able to:
``` javascript
var Juicer = require('./juicer')
module.exports = function(){
new Juicer().juice() // to access the test double function, we must `new Juicer()`
``` js
app.car = {
slowDown: function() {
app.brake(10)
}
}
```
#### replacing a module that doesn't exist yet
Once again, it is **very important** when using this feature that [`td.reset()`
is invoked after each test](1-installation.md#resetting-state-between-test-runs),
or else bizarre and terrible things will happen.
We discussed the merits of creating entirely test-scoped test doubles vs. those
that mirror their actual counterparts in the [chapter on creating test
doubles](4-creating-test-doubles.md#testdoubleobject). So, say you want to
replace `require` calls to a module that doesn't actually exist yet.
`td.replace()` supports this with an optional second argument.
## td.replace() API
``` javsacript
thisWillEqual42 = td.replace('../some-made-up-path', 42)
```
To recap, `td.replace` has two "modes", for lack of a better term, which result
in relatively disparate method signatures. So let's spell those out here:
Once set, if the subject is in a sibling directory then calling
`require('./some-made-up-path')` will return `42`. Of course, although that
replacement value can be literally anything, it will often be a `td.function()`
or `td.object()`.
### td.replace(object, propertyName, [manualReplacement])
#### Aside: third-party modules
When `td.replace`'s first argument is anything other than a string, it assumes
you're providing the object on which some property should be replaced.
If you're curious why testdouble.js doesn't support replacing third-party
modules, you can see our commentary on why we "[don't mock what we don't
own](B-frequently-asked-questions.md#why-doesnt-tdreplace-work-with-external-commonjs-modules)".
The second argument, `propertyName`, which must be a string of the same name as
some property already defined on `object` (if undefined properties were allowed
to be replaced, minor errors like misspelling would take much longer to catch).
It must be a string because `td.replace` needs to know not just its value, but
where to replace it the next time someone calls `td.reset()`.
## Browser
As discussed at the top, most of the time `td.replace` will successfully infer
the right type of fake thing to set on `object` and to return. For other cases,
you can pass a third `manualReplacement` argument to specify the value to be
set on `object[propertyName]`.
Given the eclectic array of browser namespacing, module loading, and packaging
schemes (not to mention the limited runtime introspection available in ES
`import`), testdouble.js doesn't yet try to solve the problem of injecting or
otherwise replacing test doubles to replace a subject's actual dependencies.
`td.replace` typically returns the fake thing it sets on `object`, with the
exception of constructor function properties. In that case, it will return a
plain object of test double functions to the test, but set `object[propertyName]`
to a constructor function that delegates to those test double functions only
after it's been instantiated with `new`.
For now, each browser project will need to come up with its own dependency
replacement scheme. One tried-and-true approach is to pass dependencies into a
subject so they're explicit and can be overridden easily.
### td.replace(relativePathToModule, [manualReplacement])
Another approach one could take (in apps that use a global namespace to organize
code) is to replace stuff on that namespace and unwind it in an `afterEach`. On
a jasmine or mocha project, that could be as simple as a helper like this
(untested) example:
When the first argument to `td.replace` is a string, it assumes you're replacing
a Node.js module dependency and that `relativePathToModule` is, as its name
suggests, a relative path from the test to the module being faked.
``` javascript
function replace(namespace, object, someTestDouble) {
var originalThing = namespace[object]
namespace[object] = someTestDouble
afterEach(function(){
namespace[object] = originalThing
})
}
```
In a TDD workflow, this is often the first step to figuring out where that
module should reside, and so `td.replace` will throw an error until it exists
and can be loaded. Once defined, it will return a fake thing based on the same
inferences discussed above and replace subsequent calls to `require` for that
module until the next call to `td.reset()`
That said, we'd really like to [implement this
scheme](https://github.com/testdouble/testdouble.js/issues/55) to make it easier
to get started with the library out of the box. It'd be great to see someone
[create a plugin](A-plugins.md) to support popular module loading schemes.
Also, as mentioned above, if the inference `td.replace` isn't appropriate or the
path shouldn't exist yet, a second argument `manualReplacement` can be provided
to short-circuit any attempts to load and imitate a module at
`relativePathToModule`.

@@ -19,3 +19,3 @@ # Debugging with testdouble.js

## testdouble.explain(someTestDouble)
## td.explain(someTestDouble)

@@ -22,0 +22,0 @@

global.expect = require('chai').expect;
global.context = describe;
td = require('testdouble');
global.td = require('testdouble');

@@ -5,0 +5,0 @@ afterEach(function(){

@@ -15,3 +15,4 @@ // Generated by CoffeeScript 1.10.0

callCount: 0,
description: "This test double has 0 stubbings and 0 invocations."
description: "This test double has 0 stubbings and 0 invocations.",
isTestDouble: true
});

@@ -28,3 +29,3 @@ });

});
return context('a double with some interactions', function() {
context('a double with some interactions', function() {
Given(function() {

@@ -54,8 +55,22 @@ return td.when(this.testDouble(88)).thenReturn(5);

callCount: 2,
description: "This test double has 2 stubbings and 2 invocations.\n\nStubbings:\n - when called with `(88)`, then return `5`.\n - when called with `(\"two things!\")`, then return `\"woah\"`, then `\"such\"`.\n\nInvocations:\n - called with `(88)`.\n - called with `(\"not 88\", 44)`."
description: "This test double has 2 stubbings and 2 invocations.\n\nStubbings:\n - when called with `(88)`, then return `5`.\n - when called with `(\"two things!\")`, then return `\"woah\"`, then `\"such\"`.\n\nInvocations:\n - called with `(88)`.\n - called with `(\"not 88\", 44)`.",
isTestDouble: true
});
});
});
return context('passed a non-test double', function() {
Given(function() {
return this.testDouble = 42;
});
return Then(function() {
return expect(this.result).to.deep.eq({
calls: [],
callCount: 0,
description: "This is not a test double.",
isTestDouble: false
});
});
});
});
}).call(this);

@@ -34,3 +34,3 @@ // Generated by CoffeeScript 1.10.0

Then(function() {
return td.replace === require('../../src/replace');
return td.replace === require('../../src/replace/index');
});

@@ -37,0 +37,0 @@ return Then(function() {

@@ -5,4 +5,2 @@ // Generated by CoffeeScript 1.10.0

global._ = require('lodash');
global.chai = require('chai');

@@ -9,0 +7,0 @@

// Generated by CoffeeScript 1.10.0
(function() {
var _, callDescription, callsStore, store, stringifyArgs, stringifyName, stubbingDescription, stubbingsStore;
var _, callDescription, callsStore, nullDescription, store, stringifyArgs, stringifyName, stubbingDescription, stubbingsStore;

@@ -17,2 +17,5 @@ _ = require('lodash');

var calls, stubs;
if (store["for"](testDouble, false) == null) {
return nullDescription();
}
calls = callsStore["for"](testDouble);

@@ -23,6 +26,16 @@ stubs = stubbingsStore["for"](testDouble);

calls: calls,
description: ("This test double " + (stringifyName(testDouble)) + "has " + stubs.length + " stubbings and " + calls.length + " invocations.") + stubbingDescription(stubs) + callDescription(calls)
description: ("This test double " + (stringifyName(testDouble)) + "has " + stubs.length + " stubbings and " + calls.length + " invocations.") + stubbingDescription(stubs) + callDescription(calls),
isTestDouble: true
};
};
nullDescription = function() {
return {
callCount: 0,
calls: [],
description: "This is not a test double.",
isTestDouble: false
};
};
stubbingDescription = function(stubs) {

@@ -29,0 +42,0 @@ if (stubs.length === 0) {

@@ -16,4 +16,6 @@ // Generated by CoffeeScript 1.10.0

return _.tap(createTestDoubleFunction(), function(testDouble) {
var entry;
entry = store["for"](testDouble, true);
if (name != null) {
store["for"](testDouble).name = name;
entry.name = name;
return testDouble.toString = function() {

@@ -20,0 +22,0 @@ return "[test double for \"" + name + "\"]";

// Generated by CoffeeScript 1.10.0
(function() {
var quibble;
var _, quibble, resetHandlers;
_ = require('lodash');
quibble = require('quibble');
resetHandlers = [];
module.exports = function() {
require('./store').reset();
return typeof quibble.reset === "function" ? quibble.reset() : void 0;
if (typeof quibble.reset === "function") {
quibble.reset();
}
_.each(resetHandlers, function(f) {
return f();
});
return resetHandlers = [];
};
module.exports.onNextReset = function(func) {
return resetHandlers.push(func);
};
}).call(this);

@@ -13,4 +13,7 @@ // Generated by CoffeeScript 1.10.0

},
"for": function(testDouble) {
"for": function(testDouble, createIfNew) {
var entry;
if (createIfNew == null) {
createIfNew = true;
}
if (entry = _(globalStore).find({

@@ -21,2 +24,5 @@ testDouble: testDouble

}
if (!createIfNew) {
return;
}
return _.tap(initialEntryFor(testDouble), function(newEntry) {

@@ -23,0 +29,0 @@ return globalStore.push(newEntry);

@@ -11,3 +11,3 @@ // Generated by CoffeeScript 1.10.0

explain: require('./explain'),
replace: require('./replace'),
replace: require('./replace/index'),
reset: require('./reset'),

@@ -14,0 +14,0 @@ version: process.env.npm_package_version || require('../package.json').version

{
"name": "testdouble",
"version": "1.0.0",
"version": "1.1.0",
"description": "A minimal test double library for TDD with JavaScript",

@@ -36,3 +36,3 @@ "homepage": "https://github.com/testdouble/testdouble.js",

"browser": {
"./lib/replace.js": "./lib/replace.browser.js"
"./lib/replace/module.js": "./lib/replace/module.browser.js"
},

@@ -39,0 +39,0 @@ "browserify": {

@@ -30,4 +30,4 @@ # testdouble.js

4. [Creating test doubles](docs/4-creating-test-doubles.md#creating-test-doubles)
1. [test double functions with `td.function()`](docs/4-creating-test-doubles.md#testdoublefunctionname)
2. [test double objects with `td.object()`](docs/4-creating-test-doubles.md#testdoubleobject)
1. [test double functions with `td.function()`](docs/4-creating-test-doubles.md#tdfunctionname)
2. [test double objects with `td.object()`](docs/4-creating-test-doubles.md#tdobject)
1. [objects that mirror a constructor function](docs/4-creating-test-doubles.md#objectsomeconstructorfunction)

@@ -38,3 +38,3 @@ 2. [objects that mirror an object of functions](docs/4-creating-test-doubles.md#objectsomeobjectwithfunctions)

5. [Stubbing responses](docs/5-stubbing-results.md#stubbing-behavior)
1. [td.when() API](docs/5-stubbing-results.md#testdoublewhen)
1. [td.when() API](docs/5-stubbing-results.md#tdwhen)
2. [equality argument matching](docs/5-stubbing-results.md#simple-precise-argument-stubbing)

@@ -44,9 +44,9 @@ 3. [one-liner stubbings](docs/5-stubbing-results.md#one-liner-stubbings)

5. [argument matchers](docs/5-stubbing-results.md#loosening-stubbings-with-argument-matchers)
1. [td.matchers.anything()](docs/5-stubbing-results.md#testdoublematchersanything)
2. [td.matchers.isA()](docs/5-stubbing-results.md#testdoublematchersisa)
3. [td.matchers.contains()](docs/5-stubbing-results.md#testdoublematcherscontains)
1. [td.matchers.anything()](docs/5-stubbing-results.md#tdmatchersanything)
2. [td.matchers.isA()](docs/5-stubbing-results.md#tdmatchersisa)
3. [td.matchers.contains()](docs/5-stubbing-results.md#tdmatcherscontains)
1. [matching strings](docs/5-stubbing-results.md#strings)
2. [matching arrays](docs/5-stubbing-results.md#arrays)
3. [matching objects](docs/5-stubbing-results.md#objects)
4. [td.matchers.argThat()](docs/5-stubbing-results.md#testdoublematchersargthat)
4. [td.matchers.argThat()](docs/5-stubbing-results.md#tdmatchersargthat)
6. [Stubbing callback APIs](docs/5-stubbing-results.md#stubbing-callback-apis)

@@ -59,12 +59,12 @@ 7. [Stub exceptions with thenThrow](docs/5-stubbing-results.md#stub-exceptions-with-thenthrow)

6. [Verifying invocations](docs/6-verifying-invocations.md#verifying-interactions)
1. [td.verify() API](docs/6-verifying-invocations.md#testdoubleverify)
1. [td.verify() API](docs/6-verifying-invocations.md#tdverify)
2. [equality argument matching](docs/6-verifying-invocations.md#arguments)
3. [argument matchers](docs/6-verifying-invocations.md#relaxing-verifications-with-argument-matchers)
1. [td.matchers.anything()](docs/6-verifying-invocations.md#testdoublematchersanything)
2. [td.matchers.isA()](docs/6-verifying-invocations.md#testdoublematchersisa)
3. [td.matchers.contains()](docs/6-verifying-invocations.md#testdoublematcherscontains)
1. [td.matchers.anything()](docs/6-verifying-invocations.md#tdmatchersanything)
2. [td.matchers.isA()](docs/6-verifying-invocations.md#tdmatchersisa)
3. [td.matchers.contains()](docs/6-verifying-invocations.md#tdmatcherscontains)
1. [matching strings](docs/6-verifying-invocations.md#strings)
2. [matching arrays](docs/6-verifying-invocations.md#arrays)
3. [matching objects](docs/6-verifying-invocations.md#objects)
4. [td.matchers.argThat()](docs/6-verifying-invocations.md#testdoublematchersargthat)
4. [td.matchers.argThat()](docs/6-verifying-invocations.md#tdmatchersargthat)
4. [Argument captors](docs/6-verifying-invocations.md#multi-phase-assertions-with-argument-captors)

@@ -74,13 +74,9 @@ 5. [Configuring verifications](docs/6-verifying-invocations.md#configuring-verifications)

2. [times](docs/6-verifying-invocations.md#times)
7. [Replacing dependencies with test doubles](docs/7-replacing-dependencies.md#replacing-dependencies-with-test-doubles)
7. [Replacing dependencies with test doubles](docs/7-replacing-dependencies.md#replacing-real-dependencies-with-test-doubles)
1. [for Node.js](docs/7-replacing-dependencies.md#nodejs)
1. [td.replace() API](docs/7-replacing-dependencies.md#testdoublereplacerelativepath-faketoreplace)
1. [Replacing plain functions](docs/7-replacing-dependencies.md#replacing-a-module-that-exports-a-plain-function)
2. [Replacing plain objects](docs/7-replacing-dependencies.md#replacing-a-module-that-exports-a-plain-object)
3. [Replacing a constructor function](docs/7-replacing-dependencies.md#replacing-a-module-that-exports-a-constructor-function)
4. [Replacing a module that doesn't exist (yet)](docs/7-replacing-dependencies.md#replacing-a-module-that-doesnt-exist-yet)
2. [for Browser JS](docs/7-replacing-dependencies.md#browser)
3. [td.replace() API](docs/7-replacing-dependencies.md#testdoublereplace-api)
8. [Writing custom argument matchers](docs/8-custom-matchers.md#custom-argument-matchers)
9. [Debugging with testdouble.js](docs/9-debugging.md#debugging-with-testdoublejs)
1. [td.explain() API](docs/9-debugging.md#testdoubleexplainsometestdouble)
1. [td.explain() API](docs/9-debugging.md#tdexplainsometestdouble)
10. [Plugins](docs/A-plugins.md#plugins)

@@ -87,0 +83,0 @@ 1. [testdouble-chai](https://github.com/basecase/testdouble-chai)

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc