testdouble
Advanced tools
Comparing version 1.0.0 to 1.1.0
@@ -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
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
705840
146
16002
83