Sinon.JS 1.3.0 out now

On this second day of 2012, I am happy to announce Sinon.JS 1.3.0, the latest and greatest in JavaScript test spies, stubs and mocks.

As always, Sinon.JS honors semantic versioning, meaning that if your code works with 1.0, 1.1. and/or 1.2, 1.3.0 is a drop-in replacement. Eager? get your copy right away.

Fake XMLHttpRequests and the server

The fake XHRs and server in Sinon are useful both for testing and for quick mockups. Sinon 1.3.0 includes a few improvements targeted at the mockup use case.

Fake server logic

This feature was actually introduced earlier, but slightly flawed. You can now use a bare function handler with server.respondWith. If the function calls respond on the passed in xhr object, no further processing will occur. If it does not, the next handler will be consulted as usual:

// Log each request in the console,
// like e.g. Firebug already does for normal requests

var server = sinon.fakeServer.create();
server.respondWith(function (xhr) {
    console.log(xhr.method, xhr.url, xhr.requestBody);
});

// Another handler that responds to all POSTs to /rest/*
// by sending back the POST body.
server.respondWith(function (xhr) {
    if (xhr.method == "POST" && /^\/rest\//.test(xhr.url)) {
        xhr.respond(200, {}, xhr.requestBody);
    }
});

Partially faked servers

When using Sinon for mockup development, or integration testing, you might want some requests to be faked out and others go through to the backend server. With request filters you can:

sinon.FakeXMLHttpRequest.useFilters = true;
sinon.FakeXMLHttpRequest.addFilter(function (method, url, async, username, password) {
    // Don't fake POST requests
    if (method == "POST") {
        return true;
    }
});

More details in the docs. This feature was implemented by Tim Ruffles. Thanks Tim!

Quick and dirty responds

When your fake server only has one pre-configured response, you can now pass your respondWith arguments directly to respond to do both in one call:

server.respond("GET", "/hello", ["OK"]);

This feature was implemented by Gavin Huang, thanks Gavin!

Spies

Test spies beefed up slightly in 1.3.0.

More transparent spies

Test spies now properly mirrors any properties set on the function prior to spying:

var api = {
    doIt: function () {
        api.doIt.times += 1;
        alert("Called " + api.doIt.times + " times");
    }
};

api.doIt.times = 0;

api.doIt();
sinon.spy(api, "doIt");
console.log(api.doIt.times); // "1"

New properties

Some properties where added to more conveniently get at specific calls: spy.firstCall, spy.secondCall, spy.thirdCall, spy.lastCall.

Maximilian Antoni added these properties, thanks Max!

Spy and stub inherited methods

Thanks to Felix Geisendörfer and Robin Mehner, who both convinced me in this discussion - and Felix in particular who took it upon him to implement it - Sinon will now gladly spy on and stub inherited methods (i.e. non-own-properties).

In previous versions, this was specifically prohibited to avoid allowing you to spy on methods that did not exist. I still believe this is and important measure to avoid mismatches between tests and integrated production code, but restricting inherited properties was ultimately not helpful.

Stubs

Calling callbacks

Maximilian Antoni has been busy in this version of Sinon. He also implemented some very useful methods for stubs. Whenever you have a stub that takes function arguments, you may want to be able to call those callbacks in your tests.

Sinon has enabled this for a while using stub.yields(42). The problem however, is that this must be specified up-front in a mock-like way. If you don't like the Yoda-touch of the mock, you might want to explicitly invoke callbacks after the fact instead. Now you can, using stub.yield(), stub.yieldTo(), stub.callArg() and stub.callArgWith().

var stub = sinon.stub();
stub(42, function () {
    console.log("Yeah!");
});

stub.yield(); // Prints "Yeah!"

See the docs for more details.

Returning an argument

It can be useful to tell a stub to return one of its arguments, rather than a pre-configured static value. Thanks to Gavin Huang, you now can:

var stub = sinon.stub().returnsArg(2);
stub(1, 2, 3); // Returns 3

Error messages

Sinon 1.3.0 has improved debugability on two major accounts.

Error logging

Sinon will now log certain exceptions to sinon.log. This method is intended to be overridden - by default it does nothing. By setting it to something that prints in your environment, you can gain more insight in what happens when things fail inside Sinon:

// Using Buster.JS
sinon.log = function () {
    buster.log.apply(buster, arguments);
};

// Using JsTestDriver
sinon.log = function () {
    jstestdriver.console.log.apply(jstestdriver.console, arguments);
};

// In-browser stuff
sinon.log = function () {
    console.log.apply(console, arguments);
};

The suggested fix for Buster will be default in the next release of Buster.

Object formatting

The default bundle found on the website now uses buster-format to nicely format objects in various error messages. For instance, previously sinon.assert.calledWith(spy, obj) would print something like "expected [object Object]", while now it will print a pretty string representation of the object.

It backed down from making buster-format a dependency in the last moment, because I don't want Sinon to have dependencies. This means that you don't get this feature for free on Node. buster-format will be used if it's installed in your project, otherwise, Sinon will format with util.inspect, which for the most part is just as nice.

Bug fixes

Like always, the new release also includes various bug fixes, by me and others. See the Changelog for details.

Contributors

This release welcomes 5 new contributors, bringing the total number of authors up to 15. The GitHub community and watchers are also growing. I'm very thankful to have so many nice people enthustiastically contribute to this project. I want to thank you all for helping keeping Sinon awesome through bug reports, pull requests, discussions/challenges and helping others use Sinon!

What's in Sinon's future?

I have already tagged two issues on the Sinon 1.4.0 milestone, even though I don't know when it will be out. 1.4.0 will include a fakeServer that works with the same interface on Node, and some new matchers to provide a wider variety of matching functionality (e.g. check if stub was called with a string and a number, as opposed to exact values).

If you have suggestions/requests, please report them in the issue tracker. I will be busy with/prioritizing Buster.JS for the foreseeable future, so I don't know when new Sinon features will land. I aim to do 1.4.0 sometime before the summer, and do patch-releases with bug fixes more frequently than in the past (basically, I'll finally get my shit together and start using branches actively for this project).

Published 2. January 2012 in javascript, test driven development og sinon.js.

Possibly related