What is Sinon? It is a unit test library for JavaScript.
It has 5 parts:
-
Spy: The Test Spy is designed to act as an observation point by recording the method calls made to it by the SUT as it is exercised.
-
Stub: The Test Stub replaces a real object with a test-specific object that feeds the desired indirect inputs into the system under test. Stubs do not proxy original methods. Stubs have an API for controlling behavior.
-
Mock: The mock replaces an object the system under test (SUT) depends on with a test-specific object that verifies it is being used correctly by the SUT. State expectations up-front. No need for assertions. Mocks are spies and stubs.
-
Fake Servers: Declare responses upfront "Unknown" requests get a 404 Process async requests with server.respond()
“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.”
Features: called
, callCount
, calledWith
, threw
, returned
.
-
Create a spy function
var callback = sinon.spy(); callback(); // Invoke the spy callback function callback.called; callback.callCount; callback.calledWith(arg1); callback.threw(); callback.returned(obj); callback.calledBefore(spy); callback.calledAfter(spy);
-
Turn an existing function into a spy function
sinon.spy($, "ajax"); $.ajax({ / ... / }); // Call spy version of jQuery.ajax var call = $.ajax.getCall(0); call.args; call.exception; call.returnValue; $.ajax.restore();
“Test 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.”
Example
var stub = sinon.stub(),
opts = { call: function (msg) { console.log(msg); } };
// We can control how the sinon.stub() will behave based on how it’s called!
stub.withArgs("Hello").returns("World");
stub.withArgs("Wuz").returns("Zup?");
stub.withArgs("Kapow").throws();
stub.withArgs(opts).yieldsTo("call", ["Howdy"]);
stub("Hello"); // "World"
stub(opts); // "Howdy"
// notes, all above stub.withArgs(opts) can be replaced
// with stub.yieldsTo(property, [arg1, arg2, ...])
Another example mockServer.coffee
uses ajax
, yieldsTo
“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.”
i.e.
var opts = { call: function (msg) { console.log(msg); } },
mock = sinon.mock(opts);
// You state your success criteria upfront
mock.expects("call").once().withExactArgs("Hello World");
/* ... twice, atMost, never, exactly, on, etc ... */
opts.call("Hello World");
mock.verify();
mock.restore();
"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."
Example:
var clock = sinon.useFakeTimers();
var hidden =
$("<div hidden="">Peekaboo</div>")
.appendTo(document.body).fadeIn("slow");
clock.tick(650); // slow = 600ms
hidden.css("opacity") === 1; // true
clock.restore();
clock.tick(650)
will set our time 650 ms ahead, thus
hidden.css("opacity")
will be true.
“High-level API to manipulate FakeXMLHttpRequest instances.”
var server = sinon.fakeServer.create();
server.respondWith("GET", "/twitter/api/user.json", [
200,
{"Content-Type": "application/json"},
'[{"id": 0, "tweet": "Hello World"}]'
]);
$.get("/twitter/api/user.json", function (data) {
console.log(data); // [{"id":0,"tweet":"Hello World"}]
});
server.respond();
server.restore();
So, what is the difference between using Fake Servers or just stub on the ajax call? To me, you could use either. Use Fake Servers if you want to test it on the system level rather than function levels. There you have it, how to use Sinon.JS.
[Sinon official docs] (http://sinonjs.org/docs/)
[Unit Test like a Secret Agent with Sinon.js] (http://www.elijahmanor.com/unit-test-like-a-secret-agent-with-sinon-js/)
[Sinon - Simplifying JavaScript testing] (http://cjohansen.no/talks/2011/xp-meetup/#1)
[JavaScript Test Spies, Stubs and Mocks] (http://cjohansen.no/en/javascript/javascript_test_spies_stubs_and_mocks)
[Design Goals] (http://cjohansen.no/talks/2011/xp-meetup/#6)
[一款颇具特色的前端单元测试工具——Sinon.js] (http://www.36ria.com/6194)