| space, → | next slide |
| ← | previous slide |
| d | debug mode |
| ## <ret> | go to slide # |
| c | table of contents (vi) |
| f | toggle footer |
| r | reload slides |
| z | toggle help (this) |



http://www.opensource.org/licenses/bsd-license.php

![]()
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.
"test should call subscriber": function () {
var spy = sinon.spy();
PubSub.subscribe("message", spy);
PubSub.publishSync("message", undefined);
assertTrue(spy.called);
}
function () {}spy.calledspy.calledOncespy.calledTwicespy.calledThricespy.callCount"test should call subscriber": function () {
var spy = sinon.spy();
PubSub.subscribe("message", spy);
PubSub.publishSync("message", { id: 42 });
PubSub.publishSync("message", [3, 4, 2]);
// assert(???)
}
"test should call subscriber": function () {
var spy = sinon.spy();
PubSub.subscribe("message", spy);
PubSub.publishSync("message", { id: 42 });
PubSub.publishSync("message", [3, 4, 2]);
assertTrue(spy.calledWith({ id: 42 }));
}
"test should call subscriber": function () {
var spy = sinon.spy();
PubSub.subscribe("message", spy);
PubSub.publishSync("message", { id: 42 });
PubSub.publishSync("message", [3, 4, 2]);
assertTrue(spy.calledWith({ id: 42 }));
assertEquals([3, 4, 2], spy.args[1][0]);
}
"test should call subscriber": function () {
var spy = sinon.spy();
PubSub.subscribe("message", spy);
PubSub.publishSync("message", "Many", "arguments");
PubSub.publishSync("message", 12, 34);
assertTrue(spy.calledWith("Many")); // Passes
assertTrue(spy.calledWithExactly("Many")); // Fails
}
"test should call subscriber": function () {
var spy = sinon.spy();
PubSub.subscribe("message", spy);
PubSub.publishSync("message", "Many", "arguments");
PubSub.publishSync("message", 12, 34);
assertTrue(spy.calledWith("Many"));
assertTrue(spy.calledWithExactly("Many", "arguments"));
}
"test should call subscriber": function () {
var spy = sinon.spy();
PubSub.subscribe("message", spy);
PubSub.publishSync("message", "Many", "arguments");
PubSub.publishSync("message", "Many", 34);
assertTrue(spy.alwaysCalledWith("Many")); // Passes
assertTrue(spy.alwaysCalledWithExactly("Many")); // Fails
}
"test should call subscriber": function () {
var mspy = sinon.spy();
var espy = sinon.spy();
PubSub.subscribe("message", mspy);
PubSub.subscribe("event", espy);
PubSub.publishSync("message", { id: 42 });
PubSub.publishSync("event", [3, 4, 2]);
assertTrue(mspy.calledBefore(espy));
assertTrue(espy.calledAfter(mspy));
}
spy.calledOn(obj);spy.threw();spy.returned(obj);
"test should fetch items from backend": function () {
var element = document.createElement("ol");
var list = xp.todoList.create();
sinon.spy(list, "all");
var controller = xp.listController.create(element, list);
controller.init();
assert(list.all.calledOnce);
}
sinon.spy(obj, "method") == obj.method![]()
The Test Stub replaces a real object with a test-specific object that feeds the desired indirect inputs into the system under test.
"test should call subscriber": function () {
var stub = sinon.stub();
PubSub.subscribe("message", stub);
PubSub.publishSync("message", undefined);
assertTrue(stub.called);
}
"test should fetch items from backend": function () {
var element = document.createElement("ol");
var list = xp.todoList.create();
sinon.stub(list, "all");
var controller = xp.listController.create(element, list);
controller.init();
assert(list.all.calledOnce);
}
"test should attach todo items to list": function () {
var list = xp.todoList.create();
sinon.stub(list, "all").yields([
{ text: "Do it", id: 1, done: false },
{ text: "Run, Forest!", id: 2, done: false }]);
// ...
// ...
var element = document.createElement("ol");
var controller = xp.listController.create(element, list);
controller.init();
assertEquals(2, element.childNodes.length);
assertEquals("Do it", element.childNodes[0].innerHTML);
assertEquals("Run, Forest!", element.childNodes[1].innerHTML);
}
stub.yields([args...]);stub.returns(value);stub.throws("ErrorType");yields is new in 1.1.0"test should attach todo items to list": function () {
var list = xp.todoList.create();
sinon.stub(list, "all").callsArgWith(0, [
{ text: "Do it", id: 1, done: false },
{ text: "Run, Forest!", id: 2, done: false }]);
// ...
"test should yield updated item to callback on success": function () {
sinon.stub(jQuery, "ajax").yieldsTo(
"success", '{"text":"Fetch eggs","done":true,"id":1}');
// ...
// ...
var list = xp.todoList.create();
var callback = sinon.spy();
list.completeItem(1, callback);
assert(callback.calledOnce);
assertEquals({ text: "Fetch eggs", done: true, id: 1 },
callback.args[0][0]);
}
yieldsTo is new in 1.1.0"should add item to backend": function (test) {
this.req.method = "POST";
this.req.body = "item=Are+you+there%3F";
sinon.stub(this.controller.list, "add");
controller.create(this.req, fakeHttp.res());
test.ok(this.controller.list.add.calledOnce);
test.ok(this.controller.list.add.calledWith("Are you there?"));
test.done();
}
![]()
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.
"test should fetch items from backend": function () {
var element = document.createElement("ol");
var list = xp.todoList.create();
var mock = sinon.mock(list);
mock.expects("all");
var controller = xp.listController.create(element, list);
controller.init();
mock.verify();
}
"test should attach todo items to list": function () {
var list = xp.todoList.create();
var mock = sinon.mock(list);
mock.expects("all").yields([
{ text: "Do it", id: 1, done: false },
{ text: "Run, Forest!", id: 2, done: false }]);
// ...
"test should fetch items from backend": function () {
var element = document.createElement("ol");
var list = xp.todoList.create();
var mock = sinon.mock(list);
mock.expects("all").once();
var controller = xp.listController.create(element, list);
controller.init();
mock.verify();
}
expectation.atLeast(number);expectation.atMost(number);expectation.never();expectation.once();expectation.twice();expectation.thrice();expectation.exactly(number);expectation.withArgs(arg1, arg2, ...);expectation.withExactArgs(arg1, arg2, ...);expectation.on(obj);"test something": sinon.test(function () {
this.spy(/* ... */);
this.stub(/* ... */);
this.mock(/* ... */);
});
"test should fetch items from backend": sinon.test(function () {
var element = document.createElement("ol");
var list = xp.todoList.create();
this.mock(list).expects("all").once();
var controller = xp.listController.create(element, list);
controller.init();
})
"test should yield updated item to callback on success":
sinon.test(function () {
this.stub(jQuery, "ajax").yieldsTo(
"success", '{"text":"Fetch eggs","done":true,"id":1}');
// ...
}),
"test something else": function () {
// jQuery.ajax is live again
}
TestCase("MyTest", sinon.testCase({
// All tests are sandboxed
}));
"test should fetch items from backend": function () {
var element = document.createElement("ol");
var list = xp.todoList.create();
sinon.spy(list, "all");
var controller = xp.listController.create(element, list);
controller.init();
assertTrue(list.all.calledOnce);
}
$ jstestdriver --tests all
...........................F....................................
Total 64 tests (Passed: 63; Fails: 1; Errors: 0) (198.00 ms)
Firefox 3.6.13 Linux: Run 64 tests (Passed: 63; Fails: 1; Errors 0) (198.00 ms)
ListControllerInitTest.test should fetch items from backend failed (1.00 ms): \
expected true but was false
/test/list_controller_test.js:56
Tests failed.
$ jstestdriver --tests all
...........................F....................................
Total 64 tests (Passed: 63; Fails: 1; Errors: 0) (198.00 ms)
Firefox 3.6.13 Linux: Run 64 tests (Passed: 63; Fails: 1; Errors 0) (198.00 ms)
ListControllerInitTest.test should fetch items from backend failed (1.00 ms): \
expected true but was false
/test/list_controller_test.js:56
Tests failed.
"test should fetch items from backend": function () {
var element = document.createElement("ol");
var list = xp.todoList.create();
sinon.spy(list, "all");
var controller = xp.listController.create(element, list);
controller.init();
sinon.assert.calledOnce(list.all);
}
$ jstestdriver --tests all
...........................F....................................
Total 64 tests (Passed: 63; Fails: 1; Errors: 0) (198.00 ms)
Firefox 3.6.13 Linux: Run 64 tests (Passed: 63; Fails: 1; Errors 0) (198.00 ms)
ListControllerInitTest.test should fetch items from backend failed (1.00 ms): \
expected all to be called once but was called twice
/test/list_controller_test.js:56
Tests failed.
$ jstestdriver --tests all
...........................F....................................
Total 64 tests (Passed: 63; Fails: 1; Errors: 0) (198.00 ms)
Firefox 3.6.13 Linux: Run 64 tests (Passed: 63; Fails: 1; Errors 0) (198.00 ms)
ListControllerInitTest.test should fetch items from backend failed (1.00 ms): \
expected all to be called once but was called twice
/test/list_controller_test.js:56
Tests failed.
sinon.assert.called(spy);sinon.assert.calledWith(spy, args...);sinon.assert.calledBefore(spy, otherSpy);sinon.assert.fail = function (msg) {
QUnit.ok(false, msg);
};
test("should fetch items from backend": function () {
var element = document.createElement("ol");
var list = xp.todoList.create();
this.spy(list, "all");
var controller = xp.listController.create(element, list);
controller.init();
sinon.assert.calledOnce(list.all);
});


"test should fade out element after 2secs": function () {
var p = jQuery(xp.flash.message("Uh-oh!"));
p.appendTo(document.body);
var height = p.height();
// ???
assertEquals(0, p.height());
assertEquals(0, p.parent().length);
}
setUp: function () {
this.clock = sinon.useFakeTimers();
},
tearDown: function () {
this.clock.restore();
}
"test should fade out element after 2secs": function () {
var p = jQuery(xp.flash.message("Uh-oh!"));
p.appendTo(document.body);
var height = p.height();
this.clock.tick(2000);
assertEquals(1, p.parent().length);
"test should fade out element after 2secs": function () {
var p = jQuery(xp.flash.message("Uh-oh!"));
p.appendTo(document.body);
var height = p.height();
this.clock.tick(2000);
assertEquals(1, p.parent().length);
this.clock.tick(160);
assert(p.height() < height);
"test should fade out element after 2secs": function () {
var p = jQuery(xp.flash.message("Uh-oh!"));
p.appendTo(document.body);
var height = p.height();
this.clock.tick(2000);
assertEquals(1, p.parent().length);
this.clock.tick(160);
assert(p.height() < height);
this.clock.tick(160);
assertEquals(0, p.height());
assertEquals(0, p.parent().length);
}
setUp: function () {
this.clock = sinon.useFakeTimers();
},
tearDown: function () {
this.clock.restore();
},
"test something": function () {
this.clock.tick(15);
}
"test should automatically restore timers": sinon.test(function () {
this.clock.tick(45);
});
setUp: function () {
this.fakeXhr = sinon.useFakeXMLHttpRequest();
var requests = this.requests = [];
this.fakeXhr.onCreate = function (xhr) {
requests.push(xhr);
};
},
tearDown: function () {
this.fakeXhr.restore();
}
"test should POST to /todo-items": function () {
var list = xp.todoList.create();
list.add("Fetch eggs from the store");
assertEquals(1, this.requests.length);
assertEquals("POST", this.requests[0].method);
assertEquals("/todo-items", this.requests[0].url);
}
"test should POST to /todo-items": sinon.test(function () {
var list = xp.todoList.create();
list.add("Fetch eggs from the store");
assertEquals(1, this.requests.length);
assertEquals("POST", this.requests[0].method);
assertEquals("/todo-items", this.requests[0].url);
})
"test should yield list item to callback on success": function () {
var list = xp.todoList.create();
var callback = sinon.spy();
list.add("Fetch eggs", callback);
// ...
}
"test should yield list item to callback on success": function () {
var list = xp.todoList.create();
var callback = sinon.spy();
list.add("Fetch eggs", callback);
this.requests[0].respond(
200, { "Content-Type": "application/json" },
'{"text":"Fetch eggs","done":false,"id":1}');
assert(callback.calledOnce);
assertEquals({ text: "Fetch eggs", done: false, id: 1 },
callback.args[0][0]);
}
setUp: function () {
this.server.respondWith(
"POST", "/todo-items",
[200, { "Content-Type": "application/json" },
'{"text":"Fetch eggs","done":false,"id":1}']);
}
"test should yield list item to callback on success": function () {
var list = xp.todoList.create();
var callback = sinon.spy();
list.add("Fetch eggs", callback);
this.server.respond();
assert(callback.calledOnce);
assertEquals({ text: "Fetch eggs", done: false, id: 1 },
callback.args[0][0]);
}
server.respond()