Standalone test spies, stubs and mocks for JavaScript.
No dependencies, works with any unit testing framework.
This page contains the entire Sinon.JS API documentation along with brief introductions to the concepts Sinon implements. Please ask questions on the mailing list if you're stuck. I also really appreciate suggestions to improve the documentation so Sinon.JS is easier to work with. Get in touch!
A test spy is a function that records arguments, return value, the value
of this and exception thrown (if any) for all its calls. A
test spy can be an anonymous function or it can wrap an existing
function.
Test spies are useful to test both callbacks and how certain functions/methods are used throughout the system under test. The following simplified example shows how to use spies to test how a function handles a callback:
"test should call subscribers on publish": function () {
var callback = sinon.spy();
PubSub.subscribe("message", callback);
PubSub.publishSync("message");
assertTrue(callback.called);
}
sinon.spy can also spy on existing functions. When doing
so, the original function will behave just as normal (including when
used as a constructor) but you will have access to data about all
calls. The following is a slightly contrived example:
{
setUp: function () {
sinon.spy(jQuery, "ajax");
},
tearDown: function () {
jQuery.ajax.restore(); // Unwraps the spy
},
"test should inspect jQuery.getJSON's usage of jQuery.ajax": function () {
jQuery.getJSON("/some/resource");
assert(jQuery.ajax.calledOnce);
assertEquals("/some/resource", jQuery.ajax.getCall(0).args[0].url);
assertEquals("json", jQuery.ajax.getCall(0).args[0].dataType);
}
}
sinon.spy()var spy = sinon.spy();this value,
exceptions and return values for all calls.
var spy = sinon.spy(myFunc);var spy = sinon.spy(object, "method");object.method
and replaces the original method with the spy. The spy acts exactly
like the original method in all cases. The original method can be
restored by calling object.method.restore(). The
returned spy is the function object which replaced the original
method. spy === object.method.
Spies provide a rich interface to inspect their usage. The above
examples showed the calledOnce boolean property as well as
the getCall method and the returned
object's args property. There are three ways of inspecting
call data.
The preferred approach is to use the spy's calledWith
method (and friends) because it keeps your test from being too specific
about which call did what and so on. It will return true if
the spy was ever called with the provided arguments.
"test should call subscribers with message as first argument" : function () {
var message = 'an example message';
var spy = sinon.spy();
PubSub.subscribe(message, spy);
PubSub.publishSync(message, "some payload");
assert(spy.calledWith(message));
}
If you want to be specific, you can directly check the first argument of the first call. There are two ways of achieving this:
"test should call subscribers with message as first argument" : function () {
var message = 'an example message';
var spy = sinon.spy();
PubSub.subscribe(message, spy);
PubSub.publishSync(message, "some payload");
assertEquals(message, spy.args[0][0]);
}
"test should call subscribers with message as first argument" : function () {
var message = 'an example message';
var spy = sinon.spy();
PubSub.subscribe(message, spy);
PubSub.publishSync(message, "some payload");
assertEquals(message, spy.getCall(0).args[0]);
}
The first example uses the two-dimensional args array
directly on the spy, while the second example fetches the first call
object and then accesses it's args array. Which one to use
is a matter of preference, but the recommended approach is going with
spy.calledWith(arg1, arg2, ...) unless there's a need to
make the tests highly specific.
Spy objects are objects returned from sinon.spy(). When
spying on existing methods with sinon.spy(object, method),
the following properties and methods are also available
on object.method.
withArgs. This is useful to be
more expressive in your assertions, where you can access the spy with
the same call:
"test should call method once with each argument": function () {
var object = { method: function () {} };
var spy = sinon.spy(object, "method");
spy.withArgs(42);
spy.withArgs(1);
object.method(42);
object.method(1);
assert(spy.withArgs(42).calledOnce);
assert(spy.withArgs(1).calledOnce);
}
spy.callCountspy.calledtrue if the spy was called at least oncespy.calledOncetrue if spy was called exactly oncespy.calledTwicetrue if the spy was called exactly twicespy.calledThricetrue if the spy was called exactly thricespy.firstCallspy.secondCallspy.thirdCallspy.lastCallspy.calledBefore(anotherSpy);true if the spy was called before anotherSpyspy.calledAfter(anotherSpy);true if the spy was called after anotherSpyspy.calledOn(obj);true if the spy was called at least once with obj
as this.
spy.alwaysCalledOn(obj);true if the spy was always called with obj
as this.
spy.calledWith(arg1, arg2, ...);true if spy was called at least once with the provided
arguments. Can be used for partial matching, Sinon only checks the provided
arguments against actual arguments, so a call that received the provided arguments
(in the same spots) and possibly others as well will return true.
spy.alwaysCalledWith(arg1, arg2, ...);true if spy was always called with the provided arguments
(and possibly others).
spy.calledWithExactly(arg1, arg2, ...);true if spy was called at least once with the provided arguments
and no others.
spy.alwaysCalledWithExactly(arg1, arg2, ...);true if spy was always called with the exact provided arguments.
spy.calledWithMatch(arg1, arg2, ...);true if spy was called with matching arguments
(and possibly others). This behaves the same as
spy.calledWith(sinon.match(arg1), sinon.match(arg2), ...).
spy.alwaysCalledWithMatch(arg1, arg2, ...);true if spy was always called with matching arguments
(and possibly others). This behaves the same as
spy.alwaysCalledWith(sinon.match(arg1), sinon.match(arg2), ...).
spy.calledWithNew();true if spy/stub was called the new
operator. Beware that this is inferred based on the value of
the this object and the spy
function's prototype, so it may give false positives if
you actively return the right kind of object.
spy.neverCalledWith(arg1, arg2, ...);true if the spy/stub was never called with
the provided arguments.
spy.neverCalledWithMatch(arg1, arg2, ...);true if the spy/stub was never called with
matching arguments. This behaves the same as
spy.neverCalledWith(sinon.match(arg1), sinon.match(arg2), ...).
spy.threw();true if spy threw an exception at least once.spy.threw("TypeError");true if spy threw an exception of the provided type at least once.spy.threw(obj);true if spy threw the provided exception object at least once.spy.alwaysThrew();true if spy always threw an exception.spy.alwaysThrew("TypeError");true if spy always threw an exception of the provided type.spy.alwaysThrew(obj);true if spy always threw the provided exception object.spy.returned(obj);true if spy returned the provided value at least once.
Uses deep comparison for objects and arrays.
Use spy.returned(sinon.match.same(obj)) for strict
comparison (see matchers).
spy.alwaysReturned(obj);true if spy always returned the provided value.var spyCall = spy.getCall(n);Returns the nth call. Accessing individual calls helps with more detailed behavior verification when the spy is called more than once. Example:
sinon.spy(jQuery, "ajax");
jQuery.ajax("/stuffs");
var spyCall = jQuery.ajax.getCall(0);
assertEquals("/stuffs", spyCall.args[0]);
spy.thisValuesthis objects, spy.thisValues[0] is the this
object for the first call.
spy.argsspy.args[0] is an array of
arguments recevied in the first call.
spy.exceptionsspy.exceptions[0] is
the exception thrown by the first call. If the call did not throw an
error, the value at the call's location in .exceptions
will be 'undefined'.
spy.returnValuesspy.returnValues[0] is the return
value of the first call. If the call did not explicitly return a
value, the value at the call's location in .returnValues
will be 'undefined'.
spy.reset()spy.printf("format string", [arg1, arg2, ...])%n: the name of the spy ("spy" by default)%c: the number of times the spy was called, in words ("once", "twice", etc.)%C: a list of string representations of the calls to the spy, with each call prefixed by a newline and four spaces%t: a comma-delimited list of this values the spy was called on%n: the formatted value of the nth argument passed to printf%*: a comma-delimited list of the (non-format string) arguments passed to printfvar spyCall = spy.getCall(n)Returns the nth call. Accessing individual calls helps with more detailed behavior verification when the spy is called more than once. Example:
sinon.spy(jQuery, "ajax");
jQuery.ajax("/stuffs");
var spyCall = jQuery.ajax.getCall(0);
assertEquals("/stuffs", spyCall.args[0]);
spyCall.calledOn(obj);true if obj was this for this call.spyCall.calledWith(arg1, arg2, ...);true if call received provided arguments (and possibly others).spyCall.calledWithExactly(arg1, arg2, ...);true if call received provided arguments and no others.spyCall.calledWithMatch(arg1, arg2, ...);true if call received matching arguments (and possibly others). This behaves the same as spyCall.calledWith(sinon.match(arg1), sinon.match(arg2), ...).spyCall.notCalledWith(arg1, arg2, ...);true if call did not receive provided arguments.spyCall.notCalledWithMatch(arg1, arg2, ...);true if call did not receive matching arguments. This behaves the same as spyCall.notCalledWith(sinon.match(arg1), sinon.match(arg2), ...).spyCall.threw();true if call threw an exception.spyCall.threw("TypeError");true if call threw exception of provided type.spyCall.threw(obj);true if call threw provided exception object.spyCall.thisValuethis value.spyCall.argsspyCall.exceptionspyCall.returnValueTest stubs are functions (spies) with pre-programmed behavior. They support the full test spy API in addition to methods which can be used to alter the stub's behavior.
As spies, stubs can be either anonymous, or wrap existing functions. When wrapping an existing function with a stub, the original function is not called.
Use a stub when you want to:
The following example is yet another test from Morgan Roderick's PubSubJS which shows how to create an anonymous stub that throws an exception when called.
"test should call all subscribers, even if there are exceptions" : function(){
var message = 'an example message';
var error = 'an example error message';
var stub = sinon.stub().throws();
var spy1 = sinon.spy();
var spy2 = sinon.spy();
PubSub.subscribe(message, stub);
PubSub.subscribe(message, spy1);
PubSub.subscribe(message, spy2);
PubSub.publishSync(message, undefined);
assert(spy1.called);
assert(spy2.called);
assert(stub.calledBefore(spy1));
}
Note how the stub also implements the spy interface. The test verifies that all callbacks where called, and also that the exception throwing stub was called before one of the other callbacks.
var stub = sinon.stub();var stub = sinon.stub(object, "method");object.method with a stub function. The original
function can be restored by calling object.method.restore();
(or stub.restore();). An exception is thrown if the property
is not already a function, to help avoid typos when stubbing methods.
var stub = sinon.stub(object, "method", func);object.method with a func, wrapped
in a spy. As usual, object.method.restore();
can be used to restore the original method.
var stub = sinon.stub(obj);MyConstructor,
but don't want the constructor to be invoked, use this utility
function:
var stub = sinon.createStubInstance(MyConstructor)
stub.withArgs(arg1[, arg2, ...]);"test should stub method differently based on arguments": function () {
var callback = sinon.stub();
callback.withArgs(42).returns(1);
callback.withArgs(1).throws("TypeError");
callback(); // No return value, no exception
callback(42); // Returns 1
callback(1); // Throws TypeError
}
stub.returns(obj);stub.returnsArg(index);stub.returnsArg(0); causes the stub to return the first argument.
stub.throws();Error).stub.throws("TypeError");stub.throws(obj);stub.callsArg(index);stub.callsArg(0); causes the stub to call the
first argument as a callback.
stub.callsArgOn(index, context);this context.
stub.callsArgWith(index, arg1, arg2, ...);callsArg, but with arguments to pass to the callback.stub.callsArgOnWith(index, context, arg1, arg2, ...);this context.
stub.yields([arg1, arg2, ...])callsArg. Causes the stub to call the first
callback it receives with the provided arguments (if any). If a method
accepts more than one callback, you need to use callsArg
to have the stub invoke other callbacks than the first one.
stub.yieldsOn(context, [arg1, arg2, ...])this context.
stub.yieldsTo(property, [arg1, arg2, ...])yields, yieldsTo grabs the
first matching argument, finds the callback and calls it with the
(optional) arguments:
stub.yieldsToOn(property, context, [arg1, arg2, ...])this context.
"test should fake successful ajax request": function () {
sinon.stub(jQuery, "ajax").yieldsTo("success", [1, 2, 3]);
jQuery.ajax({
success: function (data) {
assertEquals([1, 2, 3], data);
}
});
}
spy.yield([arg1, arg2, ...])spy with the given
arguments. If the spy was never called with a function argument,
yield throws an error. Also aliased as
invokeCallback.
spy.yieldTo(callback, [arg1, arg2, ...])yield, yieldTo grabs the first
matching argument, finds the callback and calls it with the (optional)
arguments:
"calling callbacks": function () {
var callback = sinon.stub();
callback({
"success": function () {
console.log("Success!");
},
"failure": function () {
console.log("Oh noes!");
}
});
callback.yieldTo("failure"); // Logs "Oh noes!"
}
spy.callArg(argNum)yield, but with an explicit argument number
specifying which callback to call. Useful if a function is called with
more than one callback, and simply calling the first callback is not
desired.
"calling the last callback": function () {
var callback = sinon.stub();
callback(function () {
console.log("Success!");
},
function () {
console.log("Oh noes!");
});
callback.callArg(1); // Logs "Oh noes!"
}
spy.callArgWith(argNum, [arg1, arg2, ...])callArg, but with arguments.
stub.callsArgAsync(index);stub.callsArgOnAsync(index, context);stub.callsArgWithAsync(index, arg1, arg2, ...);stub.callsArgOnWithAsync(index, context, arg1, arg2, ...);stub.yieldsAsync([arg1, arg2, ...])stub.yieldsOnAsync(context, [arg1, arg2, ...])stub.yieldsToAsync(property, [arg1, arg2, ...])stub.yieldsToOnAsync(property, context, [arg1, arg2, ...])Mocks (and mock expectations) are fake methods (like spies) with pre-programmed behavior (like stubs) as well as pre-programmed expectations. A mock will fail your test if it is not used as expected.
Mocks should only be used for the method under test. In every unit test, there should be one unit under test. If you want to control how your unit is being used and like stating expectations upfront (as opposed to asserting after the fact), use a mock.
Mocks come with built-in expectations that may fail your test. Thus, they enforce implementation details. The rule of thumb is: if you wouldn't add an assertion for some call specific, don't mock it. Use a stub instead. In general you should never have more than one mock (possibly with several expectations) in a single test.
Expectations implement both the spies and stubs APIs.
To see how mocks look like in Sinon.JS, here's one of the PubSubJS tests again, this time using a method as callback and using mocks to verify its behavior:
"test should call all subscribers when exceptions": function () {
var myAPI = { method: function () {} };
var spy = sinon.spy();
var mock = sinon.mock(myAPI);
mock.expects("method").once().throws();
PubSub.subscribe("message", myAPI.method);
PubSub.subscribe("message", spy);
PubSub.publishSync("message", undefined);
mock.verify();
assert(spy.calledOnce);
}
var mock = sinon.mock(obj);var expectation = mock.expects("method");obj.method with a mock function and returns it.
See expectations below.
mock.restore();mock.verify();All the expectation methods returns the expectation, meaning you can chain them. Typical usage:
sinon.mock(jQuery).expects("ajax").atLeast(2).atMost(5);
jQuery.ajax.verify();
var expectation = sinon.expectation.create([methodName]);var expectation = sinon.mock();expectation.atLeast(number);expectation.atMost(number);expectation.never();expectation.once();expectation.twice();expectation.thrice();expectation.exactly(number);number times.expectation.withArgs(arg1, arg2, ...);expectation.withExactArgs(arg1, arg2, ...);expectation.on(obj);obj as this.expectation.verify();
Fake timers is a synchronous implementation of setTimeout
and friends that Sinon.JS can overwrite the global functions with to
allow you to more easily test code using them. Fake timers provide
a clock object to pass time, which can also be used to
control Date objects created through either new
Date(); or Date.now(); (if supported by the
browser).
When faking timers with IE you also need sinon-ie-1.7.1, which should be loaded after sinon-1.7.1.js.
The fake timers can be used completely stand-alone by downloading sinon-timers-1.7.1. When using the fake timers in IE you also need sinon-timers-ie-1.7.1. Load it after the first file.
{
setUp: function () {
this.clock = sinon.useFakeTimers();
},
tearDown: function () {
this.clock.restore();
},
"test should animate element over 500ms" : function(){
var el = jQuery("<div></div>");
el.appendTo(document.body);
el.animate({ height: "200px", width: "200px" });
this.clock.tick(510);
assertEquals("200px", el.css("height"));
assertEquals("200px", el.css("width"));
}
}
var clock = sinon.useFakeTimers();
Causes Sinon to replace the global setTimeout,
clearTimeout, setInterval,
clearInterval and Date with a custom
implementation which is bound to the returned clock
object.
var clock = sinon.useFakeTimers(now);var clock = sinon.useFakeTimers([now, ]prop1, prop2, ...);clock.tick(ms);ms milliseconds. Causes all timers
scheduled within the affected time range to be called.
clock.restore();tearDown.XMLHttpRequest API reference
Provides a fake implementation of XMLHttpRequest and
provides several interfaces for manipulating objects created by it. Also
fakes the native XMLHttpRequest
and ActiveXObject (if available, and only
for XMLHTTP progids). Helps with testing requests made
with XHR.
When faking XHR with IE you also need sinon-ie-1.7.1, which should be loaded after sinon-1.7.1.js.
The fake server and XHR can be used completely stand-alone by downloading sinon-server-1.7.1. When using the fake server in IE you also need sinon-ie-1.7.1. Load it after the first file.
{
setUp: function () {
this.xhr = sinon.useFakeXMLHttpRequest();
var requests = this.requests = [];
this.xhr.onCreate = function (xhr) {
requests.push(xhr);
};
},
tearDown: function () {
this.xhr.restore();
},
"test should fetch comments from server" : function () {
var callback = sinon.spy();
myLib.getCommentsFor("/some/article", callback);
assertEquals(1, this.requests.length);
this.requests[0].respond(200, { "Content-Type": "application/json" },
'[{ "id": 12, "comment": "Hey there" }]');
assert(callback.calledWith([{ id: 12, comment: "Hey there" }]));
}
}
sinon.useFakeXMLHttpRequestvar xhr = sinon.useFakeXMLHttpRequest();XMLHttpRequest object
in browsers that support it with a custom implementation which does
not send actual requests. In browsers that support
ActiveXObject, this constructor is replaced, and fake
objects are returned for XMLHTTP progIds. Other progIds,
such as XMLDOM are left untouched.
xhr.onCreate = function (xhr) {};onCreate property of the
returned object from useFakeXMLHttpRequest() you can
subscribe to newly created FakeXMLHttpRequest
objects. See below for the fake xhr object API. Using this observer
means you can still reach objects created by
e.g. jQuery.ajax (or other abstractions/frameworks).
xhr.restore();FakeXMLHttpRequest interfacerequest.urlrequest.methodrequest.requestHeadersAn object of all request headers, i.e.:
{
"Accept": "text/html, */*",
"Connection": "keep-alive"
}
request.requestBodyrequest.statusrespond below).
request.statusTextrespond
method is called (see below).
request.asyncrequest.usernamerequest.passwordrequest.responseXMLrespond, this property is
populated with a parsed document if response headers indicate as much
(see the spec).
request.getResponseHeader(header);respond).
request.getAllResponseHeaders();
When using Sinon.JS for mockups or partial integration/functional
testing, you might want to fake some requests, while allowing others to
go throught to the backend server. With
filtered FakeXMLHttpRequests (new in Sinon 1.3.0), you can.
FakeXMLHttpRequest.useFilters (default false)true, Sinon will check added filters if
certain requests should be "unfaked".
FakeXMLHttpRequest.addFilter(fn)xhr.open is called, with the
exact same arguments (method, url,
async, username, password). If
the filter returns truthy, the request will not be faked.
request.setResponseHeaders(object);{ "Content-Type": "text/html", /*
... */ }, updates the readyState property and
fires onreadystatechange.
request.setResponseBody(body);readyState property and
fires onreadystatechange. Additionally,
populates responseXML with a parsed document
if response headers indicate as much.
request.respond(status, headers, body);status and
statusText properties. Status should be a number, the
status text is looked up from sinon.FakeXMLHttpRequest.statusCodes.
request.autoRespond(ms);ms argument. Note that this feature is intended to
help during mockup development, and is not suitable for use in tests.
High-level API to manipulate FakeXMLHttpRequest instances.
For help with handling JSON-P please refer to our notes below
{
setUp: function () {
this.server = sinon.fakeServer.create();
},
tearDown: function () {
this.server.restore();
},
"test should fetch comments from server" : function () {
this.server.respondWith("GET", "/some/article/comments.json",
[200, { "Content-Type": "application/json" },
'[{ "id": 12, "comment": "Hey there" }]']);
var callback = sinon.spy();
myLib.getCommentsFor("/some/article", callback);
this.server.respond();
sinon.assert.calledWith(callback, [{ id: 12, comment: "Hey there" }]));
}
}
var server = sinon.fakeServer.create();sinon.useFakeXMLHttpRequest().
var server = sinon.fakeServerWithClock.create();onreadystatechange.
server.respondWith(response);
response can be on of three things:
[200, { "Content-Type": "text/html", "Content-Length": 2 }, "OK"]
Default status is 200 and default headers are none. Causes
the server to respond to any request not matched by
another response with the provided data. The default
catch-all response is [404, {}, ""].
When the response is a function, it will be passed the request object. You must manually call respond on it to complete the request.
server.respondWith(url, response);/posts/1.
server.respondWith(method, url, response);method requests to the given URL with the
given response. method is an HTTP verb.
server.respondWith(urlRegExp, response);/\/post/\d+
If the response is a function, it will be passed any capture groups
from the regular expression along with the XMLHttpRequest object:
server.respondWith(/\/todo-items\/(\d+)/, function (xhr, id) {
xhr.respond(200, { "Content-Type": "application/json" }, '[{ "id": ' + id + ' }]');
});
server.respondWith(method, urlRegExp, response);method requests to URLs matching the
regular expression.
server.respond();respondWith match, the
default response is [404, {}, ""]. Synchronous requests
are responded to immediately, so make sure to call
respondWith upfront. If called with arguments,
respondWith will be called with those arguments before
responding to requests.
server.autoRespond = true;srv.respondWith automatically after every request.
server.autoRespondAfter = ms;server.fakeHTTPMethodstrue, server will find _method
parameter in POST body and recognize that as the actual
method. Supports a pattern common to Ruby on Rails applications. For
custom HTTP method faking,
override server.getHTTPMethod(request).
server.getHTTPMethod(request)request.method. When server.fakeHTTPMethods
is true, the method will return the value of the _method
parameter if the method is "POST". This method can be overrided to
provide custom behavior.
server.restore();JSON-P doesn't use Ajax requests, which is what the fake server is concerned with. A JSON-P request actually creates a script element and inserts it into the document. There is no sensible/unobtrusive enough way to fake this automatically. Your best option is to simply stub jQuery in this case:
sinon.stub(jQuery, "ajax");
sinon.assert.calledOnce(jQuery.ajax);
Potentially we could of had the fake server detect jQuery and fake any calls to jQuery.ajax when JSON-P is used, but that felt like a compromise in the focus of the Sinon project compared to simply documenting the above work-around.
Sinon.JS ships with a set of assertions that mirror most behavior verification methods and properties on spies and stubs. The advantage of using the assertions is that failed expectations on stubs and spies can be expressed directly as assertion failures with detailed and helpful error messages.
To make sure assertions integrate nicely with your test framework, you
should customize either sinon.assert.fail or
sinon.assert.failException and look into
sinon.assert.expose and
sinon.assert.pass.
The assertions can be used with either spies or stubs.
"test should call subscribers with message as first argument" : function () {
var message = 'an example message';
var spy = sinon.spy();
PubSub.subscribe(message, spy);
PubSub.publishSync(message, "some payload");
sinon.assert.calledOnce(spy);
sinon.assert.calledWith(spy, message);
}
sinon.assert.fail(message)sinon.assert.failException. If your testing
framework looks for assertion errors by checking for a specific
exception, you can simply override the kind of exception thrown. If
that does not fit with your testing framework of choice, override
the fail method to do the right thing.
sinon.assert.failExceptionsinon.assert.pass(assertion)sinon.assert.notCalled(spy)sinon.assert.called(spy)sinon.assert.calledOnce(spy)sinon.assert.calledTwice()sinon.assert.calledThrice()sinon.assert.callCount(spy, num)num times.
sinon.assert.callOrder(spy1, spy2, ...)sinon.assert.calledOn(spy, obj)obj as
its this value.
sinon.assert.alwaysCalledOn(spy, obj)obj as
its this value.
sinon.assert.calledWith(spy, arg1, arg2, ...)sinon.assert.alwaysCalledWith(spy, arg1, arg2, ...)sinon.assert.neverCalledWith(spy, arg1, arg2, ...)sinon.assert.calledWithExactly(spy, arg1, arg2, ...)sinon.assert.alwaysCalledWithExactly(spy, arg1, arg2, ...)sinon.assert.calledWithMatch(spy, arg1, arg2, ...)sinon.assert.calledWith(spy, sinon.match(arg1), sinon.match(arg2), ...).
sinon.assert.alwaysCalledWithMatch(spy, arg1, arg2, ...)sinon.assert.alwaysCalledWith(spy, sinon.match(arg1), sinon.match(arg2), ...).
sinon.assert.neverCalledWithMatch(spy, arg1, arg2, ...)sinon.assert.neverCalledWith(spy, sinon.match(arg1), sinon.match(arg2), ...).
sinon.assert.threw(spy, exception)sinon.assert.alwaysThrew(spy, exception)sinon.assert.expose(object, options)Exposes assertions into another object, to better integrate with the test framework. For instance, JsTestDriver uses global assertions, and to make Sinon.JS assertions appear alongside them, you can do:
sinon.assert.expose(this);
This will give you assertCalled(spy),
assertCallOrder(spy1, spy2, ...) and so on.
The method accepts an optional options object with two
options. prefix is a prefix to give assertions. By
default it is "assert", so sinon.assert.called becomes
target.assertCalled. By passing a blank string, the
exposed method will be target.called. The second
option, includeFail is true by default, and copies
over the fail and failException
properties.
Matchers can be passed as arguments to spy.calledWith,
spy.returned and the corresponding
sinon.assert functions as well as
spy.withArgs. Matchers allow to be either
more fuzzy or more specific about the expected value.
"test should assert fuzzy": function () {
var book = {
pages: 42,
author: "cjno"
};
var spy = sinon.spy();
spy(book);
sinon.assert.calledWith(spy, sinon.match({ author: "cjno" }));
sinon.assert.calledWith(spy, sinon.match.has("pages", 42));
}
"test should stub method differently based on argument types": function () {
var callback = sinon.stub();
callback.withArgs(sinon.match.string).returns(true);
callback.withArgs(sinon.match.number).throws("TypeError");
callback("abc"); // Returns true
callback(123); // Throws TypeError
}
sinon.match(number)sinon.match(string)sinon.match(regexp)sinon.match(object)expectation. This supports nested matchers.sinon.match(function)sinon.match.anysinon.match.definedsinon.match.truthysinon.match.falsysinon.match.boolsinon.match.numbersinon.match.stringsinon.match.objectsinon.match.funcsinon.match.arraysinon.match.regexpsinon.match.datesinon.match.same(ref)ref.sinon.match.typeOf(type)type can be one of
"undefined",
"null",
"boolean",
"number",
"string",
"object",
"function",
"array",
"regexp" or
"date".
sinon.match.instanceOf(type)sinon.match.has(property[, expectation])sinon.match.hasOwn(property[, expectation])sinon.match.has but the property must be defined by the value itself. Inherited properties are ignored.
All matchers implement and and or. This
allows to logically combine mutliple matchers. The result is a new
matchers that requires both (and) or one of the matchers (or) to
return true.
var stringOrNumber = sinon.match.string.or(sinon.match.number);
var bookWithPages = sinon.match.instanceOf(Book).and(sinon.match.has("pages"));
Custom matchers are created with the sinon.match factory
which takes a test function and an optional message. The test function takes a
value as the only argument, returns true if the
value matches the expectation and false otherwise.
The message string is used to generate the error message in case the
value does not match the expectation.
var trueIsh = sinon.match(function (value) {
return !!value;
}, "trueIsh");
Sandboxes simplify working with fakes that need to be restored and/or verified. If you're using fake timers, fake XHR, or you are stubbing/spying on globally accessible properties you should use a sandbox to ease cleanup. By default the spy, stub and mock properties of the sandbox is bound to whatever object the function is run on, so if you don't want to manually restore(), you have to use this.spy() instead of sinon.spy() (and stub, mock).
"test using sinon.test sandbox": sinon.test(function () {
var myAPI = { method: function () {} };
this.mock(myAPI).expects("method").once();
PubSub.subscribe("message", myAPI.method);
PubSub.publishSync("message", undefined);
})
var sandbox = sinon.sandbox.create();var sandbox = sinon.sandbox.create(config);
The sinon.sandbox.create(config) method is mostly an
integration feature, and as an end-user of Sinon.JS you will
probably not need it.
Creates a pre-configured sandbox object. The configuration can instruct the sandbox to include fake timers, fake server, and how to interact with these. The default configuration looks like:
sinon.defaultConfig = {
// ...
injectInto: null,
properties: ["spy", "stub", "mock", "clock", "server", "requests"],
useFakeTimers: true,
useFakeServer: true
}
injectIntoinjectInto configuration option can
name an object to add properties to. Usually, this is set by
sinon.test such that it is the this
value in a given test function.
propertiesserver property show up
in the target object, you also have to
set useFakeServer to true.
useFakeTimerstrue, the sandbox will have a clock
property. Can also be an array of timer properties to fake.
useFakeServer
If true, server and
requests properties are added to the sandbox. Can
also be an object to use for fake server. The default one
is sinon.fakeServer, but if you're using jQuery 1.3.x
or some other library that does not set the XHR's
onreadystatechange handler, you might want to do:
sinon.config = {
useFakeServer: sinon.fakeServerWithClock
};
sandbox.spy();sinon.spy, only also adds the returned
spy to the internal collection of fakes for easy restoring
through sandbox.restore().
sandbox.stub();sinon.stub, only also adds the
returned stub to the internal collection of fakes for easy restoring
through sandbox.restore(). The sandbox stub
method can also be used to stub any kind of property. This is useful
if you need to override an object's property for the duration of a
test, and have it restored when the test completes.
sandbox.mock();sinon.mock, only also adds the returned
mock to the internal collection of fakes for easy restoring
through sandbox.restore().
sandbox.useFakeTimers();clock object to the sandbox
such that it too is restored when
calling sandbox.restore().
Access through sandbox.clock.
sandbox.useFakeXMLHttpRequest();sandbox.restore(). Access
requests through sandbox.requests.
sandbox.useFakeServer();sandbox.restore(). Access
requests through sandbox.requests and server through
sandbox.server.
sandbox.restore();
Wrapping test methods in sinon.test allows Sinon.JS to
automatically create and manage sandboxes for you. The function's
behavior can be configured through sinon.config.
var wrappedFn = sinon.test(fn);wrappedFn function works exactly like the original
one in all respect - in addition a sandbox object is created and
automatically restored when the function finishes a call. By default
the spy, stub and mock properties of the sandbox is bound to whatever
object the function is run on, so you can do this.spy()
(and stub, mock) and it works exactly like sandbox.spy()
(and stub, mock), except you don't need to manually restore().
The configuration controls how Sinon binds properties when
using sinon.test. The default configuration looks like:
{
injectIntoThis: true,
injectInto: null,
properties: ["spy", "stub", "mock", "clock", "server", "requests"],
useFakeTimers: true,
useFakeServer: true
}
Simply set sinon.config to override any or all of these,
e.g.:
sinon.config = {
useFakeTimers: false,
useFakeServer: false
}
In this case, defaults are used for the non-existent properties. Additionally, sandboxes and tests will not have automatic access to the fake timers and fake server when using this configuration.
injectIntoThisthis object of
the test function. Default true.
injectIntonull (default)
and injectIntoThis is false (not default),
the properties are passed as arguments to the test function instead.
properties["spy", "stub", "mock", "clock", "server",
"requests"]. However, the last three properties are only bound
if the following two configuration options are true
(which is the default).
useFakeTimersclock property to
be exposed. Default is true.useFakeServerserver and requests properties to be
exposed. Default is true.
If you need the behavior of sinon.test for more than one
test method in a test case, you can use sinon.testCase,
which behaves exactly like wrapping each test in sinon.test
with one exception: setUp and tearDown can
share fakes.
var obj = sinon.testCase({});Sinon.JS has a few utilities used internally in lib/sinon.js. Unless the method in question is documented here, it should not be considered part of the public API, and thus is subject to change.
sinon.createStubInstance(constructor)sinon.format(object)sinon.log(string)sinon.log = function (message) {
jstestdriver.console.log(message);
};
Sinon uses Semantic versioning.
Copyright 2010 - 2012, Christian Johansen. Released under the BSD license.