unit testing javascript applications
DESCRIPTION
An in depth look at mocha and sinon. Slides show how to use both to write unit tests and mock objects for your JavaScript applicationTRANSCRIPT
![Page 1: Unit Testing JavaScript Applications](https://reader037.vdocuments.mx/reader037/viewer/2022102422/554a4ecfb4c90531228b4929/html5/thumbnails/1.jpg)
Mocha First StepsInstalling and running tests
![Page 2: Unit Testing JavaScript Applications](https://reader037.vdocuments.mx/reader037/viewer/2022102422/554a4ecfb4c90531228b4929/html5/thumbnails/2.jpg)
Agenda
• JS Unit Testing
• A first Mocha test
• Running tests with Karma
• IDE integration
![Page 3: Unit Testing JavaScript Applications](https://reader037.vdocuments.mx/reader037/viewer/2022102422/554a4ecfb4c90531228b4929/html5/thumbnails/3.jpg)
Getting Ready To Test
• JS Unit tests (try) make sure our JS code works well
![Page 4: Unit Testing JavaScript Applications](https://reader037.vdocuments.mx/reader037/viewer/2022102422/554a4ecfb4c90531228b4929/html5/thumbnails/4.jpg)
Project Tree
index.html - src - main.js - buttons.js - player.js - style - master.css - home.css
![Page 5: Unit Testing JavaScript Applications](https://reader037.vdocuments.mx/reader037/viewer/2022102422/554a4ecfb4c90531228b4929/html5/thumbnails/5.jpg)
Project Treeindex.html test.html - src - main.js - buttons.js - player.js - style - master.css - home.css - spec - test_button.js - test_player.js
![Page 6: Unit Testing JavaScript Applications](https://reader037.vdocuments.mx/reader037/viewer/2022102422/554a4ecfb4c90531228b4929/html5/thumbnails/6.jpg)
What Mocha Isn’t
• No UI / CSS testing
• No server testing
![Page 7: Unit Testing JavaScript Applications](https://reader037.vdocuments.mx/reader037/viewer/2022102422/554a4ecfb4c90531228b4929/html5/thumbnails/7.jpg)
Testing How
![Page 8: Unit Testing JavaScript Applications](https://reader037.vdocuments.mx/reader037/viewer/2022102422/554a4ecfb4c90531228b4929/html5/thumbnails/8.jpg)
Testing Libraries
• Let’s try to write test program for Array
• Verify indexOf(...) actually works
![Page 9: Unit Testing JavaScript Applications](https://reader037.vdocuments.mx/reader037/viewer/2022102422/554a4ecfb4c90531228b4929/html5/thumbnails/9.jpg)
Array#indexof
var arr1 = [10, 20, 30, 40]; if ( arr1.indexOf(20) === 1 ) { console.log('success!'); } else { console.log('error'); }
![Page 10: Unit Testing JavaScript Applications](https://reader037.vdocuments.mx/reader037/viewer/2022102422/554a4ecfb4c90531228b4929/html5/thumbnails/10.jpg)
What Went Wrong
• Hard to debug
• Hard to run automatically
![Page 11: Unit Testing JavaScript Applications](https://reader037.vdocuments.mx/reader037/viewer/2022102422/554a4ecfb4c90531228b4929/html5/thumbnails/11.jpg)
We Need …
![Page 12: Unit Testing JavaScript Applications](https://reader037.vdocuments.mx/reader037/viewer/2022102422/554a4ecfb4c90531228b4929/html5/thumbnails/12.jpg)
We Need …
![Page 13: Unit Testing JavaScript Applications](https://reader037.vdocuments.mx/reader037/viewer/2022102422/554a4ecfb4c90531228b4929/html5/thumbnails/13.jpg)
Testing Libraries
• A testing library tells you how to structure your testing code
• We’ll use mochahttp://visionmedia.github.io/mocha/
![Page 14: Unit Testing JavaScript Applications](https://reader037.vdocuments.mx/reader037/viewer/2022102422/554a4ecfb4c90531228b4929/html5/thumbnails/14.jpg)
Hello Mochavar assert = chai.assert; var array = [10,20,30,40]; describe('Array', function() { ! describe('#indexOf()', function() { ! it('should return -1 when the value is not present', function() { assert.equal(array.indexOf(7), -1); } ); }); });
![Page 15: Unit Testing JavaScript Applications](https://reader037.vdocuments.mx/reader037/viewer/2022102422/554a4ecfb4c90531228b4929/html5/thumbnails/15.jpg)
Hello Mocha
• describe() defines a block
• it() defines functionality
![Page 16: Unit Testing JavaScript Applications](https://reader037.vdocuments.mx/reader037/viewer/2022102422/554a4ecfb4c90531228b4929/html5/thumbnails/16.jpg)
Assertions
• Uses a separate assertions library
• I went with Chai
• http://chaijs.com/
![Page 17: Unit Testing JavaScript Applications](https://reader037.vdocuments.mx/reader037/viewer/2022102422/554a4ecfb4c90531228b4929/html5/thumbnails/17.jpg)
Running Our Test: Karma
![Page 18: Unit Testing JavaScript Applications](https://reader037.vdocuments.mx/reader037/viewer/2022102422/554a4ecfb4c90531228b4929/html5/thumbnails/18.jpg)
Meet Karma
• A test runner for JS
• Integrates with many IDEs
• Integrates with CI servers
• http://karma-runner.github.io/0.10/index.html
![Page 19: Unit Testing JavaScript Applications](https://reader037.vdocuments.mx/reader037/viewer/2022102422/554a4ecfb4c90531228b4929/html5/thumbnails/19.jpg)
Karma Architecture
Karma Server
![Page 20: Unit Testing JavaScript Applications](https://reader037.vdocuments.mx/reader037/viewer/2022102422/554a4ecfb4c90531228b4929/html5/thumbnails/20.jpg)
Karma Getting Started
# run just once to install npm install karma -g # create a project directory mkdir myproject cd myproject # create karma configuration file karma init
![Page 21: Unit Testing JavaScript Applications](https://reader037.vdocuments.mx/reader037/viewer/2022102422/554a4ecfb4c90531228b4929/html5/thumbnails/21.jpg)
Karma Config
• Just a JavaScript file
• keys determine how test should run
![Page 22: Unit Testing JavaScript Applications](https://reader037.vdocuments.mx/reader037/viewer/2022102422/554a4ecfb4c90531228b4929/html5/thumbnails/22.jpg)
Karma Config
• files is a list of JS files to include in the test
• Can use wildcards
![Page 23: Unit Testing JavaScript Applications](https://reader037.vdocuments.mx/reader037/viewer/2022102422/554a4ecfb4c90531228b4929/html5/thumbnails/23.jpg)
Karma Config
• browsers is a list of supported browsers
![Page 24: Unit Testing JavaScript Applications](https://reader037.vdocuments.mx/reader037/viewer/2022102422/554a4ecfb4c90531228b4929/html5/thumbnails/24.jpg)
Running Tests
# start a karma server karma start # execute tests karma run
![Page 25: Unit Testing JavaScript Applications](https://reader037.vdocuments.mx/reader037/viewer/2022102422/554a4ecfb4c90531228b4929/html5/thumbnails/25.jpg)
IDE Integration
![Page 26: Unit Testing JavaScript Applications](https://reader037.vdocuments.mx/reader037/viewer/2022102422/554a4ecfb4c90531228b4929/html5/thumbnails/26.jpg)
What We Learned
• Mocha is a JS library that helps us write unit tests
• Karma is a JS library that helps us run them
![Page 27: Unit Testing JavaScript Applications](https://reader037.vdocuments.mx/reader037/viewer/2022102422/554a4ecfb4c90531228b4929/html5/thumbnails/27.jpg)
Q & A
![Page 28: Unit Testing JavaScript Applications](https://reader037.vdocuments.mx/reader037/viewer/2022102422/554a4ecfb4c90531228b4929/html5/thumbnails/28.jpg)
Advanced MochaHow to write awesome tests
![Page 29: Unit Testing JavaScript Applications](https://reader037.vdocuments.mx/reader037/viewer/2022102422/554a4ecfb4c90531228b4929/html5/thumbnails/29.jpg)
Agenda
• Flow control: before, after, beforeEach, afterEach
• Writing async tests
• Fixtures and DOM testing
![Page 30: Unit Testing JavaScript Applications](https://reader037.vdocuments.mx/reader037/viewer/2022102422/554a4ecfb4c90531228b4929/html5/thumbnails/30.jpg)
Let’s Flowdescribe('Test 1', function() { it('should do X', function() { var p1 = new Player('bob'); var p2 = new Player('John'); var game = new GameEngine(p1, p2); // test stuff with game }); it('should do Y', function() { var p1 = new Player('bob'); var p2 = new Player('John'); var game = new GameEngine(p1, p2); // test stuff with game }); });
![Page 31: Unit Testing JavaScript Applications](https://reader037.vdocuments.mx/reader037/viewer/2022102422/554a4ecfb4c90531228b4929/html5/thumbnails/31.jpg)
Let’s Flowdescribe('Test 1', function() { it('should do X', function() { var p1 = new Player('bob'); var p2 = new Player('John'); var game = new GameEngine(p1, p2); // test stuff with game }); it('should do Y', function() { var p1 = new Player('bob'); var p2 = new Player('John'); var game = new GameEngine(p1, p2); // test stuff with game }); });
Same code...
![Page 32: Unit Testing JavaScript Applications](https://reader037.vdocuments.mx/reader037/viewer/2022102422/554a4ecfb4c90531228b4929/html5/thumbnails/32.jpg)
A Better Scheme• beforeEach() runs
before each test
• also has:
• afterEach() for cleanups
• before() and after() run once in the suite
describe('Test 1', function() {! var game;! ! beforeEach(function() {! var p1 = new Player('bob');! var p2 = new Player('John');! game = new GameEngine(p1, p2);! });! ! it('should do X', function() {! // test stuff with game! });!! ! it('should do Y', function() {! // test stuff with game! });!});
![Page 33: Unit Testing JavaScript Applications](https://reader037.vdocuments.mx/reader037/viewer/2022102422/554a4ecfb4c90531228b4929/html5/thumbnails/33.jpg)
Async Testing
![Page 34: Unit Testing JavaScript Applications](https://reader037.vdocuments.mx/reader037/viewer/2022102422/554a4ecfb4c90531228b4929/html5/thumbnails/34.jpg)
Async Theory
var x = 10
test x x has the right value testing here is OK
![Page 35: Unit Testing JavaScript Applications](https://reader037.vdocuments.mx/reader037/viewer/2022102422/554a4ecfb4c90531228b4929/html5/thumbnails/35.jpg)
Async Theory
$.get(...)
test result Can’t test now, result not yet ready
![Page 36: Unit Testing JavaScript Applications](https://reader037.vdocuments.mx/reader037/viewer/2022102422/554a4ecfb4c90531228b4929/html5/thumbnails/36.jpg)
Async Theory
• Async calls take callbacks
• We should tell mocha to wait
![Page 37: Unit Testing JavaScript Applications](https://reader037.vdocuments.mx/reader037/viewer/2022102422/554a4ecfb4c90531228b4929/html5/thumbnails/37.jpg)
Async Code
describe('Test 1', function() { it('should do wait', function(done) { setTimeout(function() { // now we can test result assert(true); done(); }, 1000); }); });
![Page 38: Unit Testing JavaScript Applications](https://reader037.vdocuments.mx/reader037/viewer/2022102422/554a4ecfb4c90531228b4929/html5/thumbnails/38.jpg)
Async Code
describe('Test 1', function() { it('should do wait', function(done) { setTimeout(function() { // now we can test result assert(true); done(); }, 1000); }); });
Taking a function argument tells mocha the test will only end after it’s called
![Page 39: Unit Testing JavaScript Applications](https://reader037.vdocuments.mx/reader037/viewer/2022102422/554a4ecfb4c90531228b4929/html5/thumbnails/39.jpg)
Async Code
describe('Test 1', function() { it('should do wait', function(done) { setTimeout(function() { // now we can test result assert(true); done(); }, 1000); }); });
Calling the callback ends the test
![Page 40: Unit Testing JavaScript Applications](https://reader037.vdocuments.mx/reader037/viewer/2022102422/554a4ecfb4c90531228b4929/html5/thumbnails/40.jpg)
Async Notes
• Always call done() or your test will fail on timeout
• Default timeout is 2 seconds
![Page 41: Unit Testing JavaScript Applications](https://reader037.vdocuments.mx/reader037/viewer/2022102422/554a4ecfb4c90531228b4929/html5/thumbnails/41.jpg)
Controlling Timeouts
describe('Test 1', function() { // set suite specific timeout this.timeout(500); it('should do wait', function(done) { // test specific timeout this.timeout(2000); }); });
![Page 42: Unit Testing JavaScript Applications](https://reader037.vdocuments.mx/reader037/viewer/2022102422/554a4ecfb4c90531228b4929/html5/thumbnails/42.jpg)
Same goes for Ajax
describe('Test 1', function() { // set suite specific timeout this.timeout(5000); it('should get user photo', function(done) { $.get('profile.png', function(data) { // run tests on data done(); }); }); });
![Page 43: Unit Testing JavaScript Applications](https://reader037.vdocuments.mx/reader037/viewer/2022102422/554a4ecfb4c90531228b4929/html5/thumbnails/43.jpg)
DOM Testing
![Page 44: Unit Testing JavaScript Applications](https://reader037.vdocuments.mx/reader037/viewer/2022102422/554a4ecfb4c90531228b4929/html5/thumbnails/44.jpg)
Theory
body
“Real” HTML “Test” HTML
body
h1
div div
img
![Page 45: Unit Testing JavaScript Applications](https://reader037.vdocuments.mx/reader037/viewer/2022102422/554a4ecfb4c90531228b4929/html5/thumbnails/45.jpg)
Theory
body
“Real” HTML “Test” HTML
body
h1
div div
img img
![Page 46: Unit Testing JavaScript Applications](https://reader037.vdocuments.mx/reader037/viewer/2022102422/554a4ecfb4c90531228b4929/html5/thumbnails/46.jpg)
Theory
$('img.thumbnail').css({ width: 200, height: 200 });
<img class="thumbmail" src="home.png" />
fixture.html
images.js
![Page 47: Unit Testing JavaScript Applications](https://reader037.vdocuments.mx/reader037/viewer/2022102422/554a4ecfb4c90531228b4929/html5/thumbnails/47.jpg)
Using Fixtures
before(function() { fixture_el = document.createElement('div'); fixture_el.id = "fixture"; ! document.body.appendChild(fixture_el); }); !beforeEach(function() { fixture_el.innerHTML = window.__html__["fixture.html"]; }); !
![Page 48: Unit Testing JavaScript Applications](https://reader037.vdocuments.mx/reader037/viewer/2022102422/554a4ecfb4c90531228b4929/html5/thumbnails/48.jpg)
Almost Ready
• HTML files are not served by default
• We need to tell karma to serve it
![Page 49: Unit Testing JavaScript Applications](https://reader037.vdocuments.mx/reader037/viewer/2022102422/554a4ecfb4c90531228b4929/html5/thumbnails/49.jpg)
Serving HTMLs• Modify files section to include the last
(HTML) pattern
// list of files / patterns to load in the browser files: [ 'lib/**/*.js', 'plugins/**/*.js', 'test/fixtures/*.html', 'spec/*.js' ],
![Page 50: Unit Testing JavaScript Applications](https://reader037.vdocuments.mx/reader037/viewer/2022102422/554a4ecfb4c90531228b4929/html5/thumbnails/50.jpg)
Testing a jQuery Plugin
it('should change the header text lowercase', function() { $('.truncate').succinct({ size: 100 }); ! var result = $('.truncate').text(); assert.equal( result.length , 100 ); });
![Page 51: Unit Testing JavaScript Applications](https://reader037.vdocuments.mx/reader037/viewer/2022102422/554a4ecfb4c90531228b4929/html5/thumbnails/51.jpg)
Fixtures & DOM
• Define DOM fragments in HTML files
• Load from test suite
• Test and clean up
![Page 52: Unit Testing JavaScript Applications](https://reader037.vdocuments.mx/reader037/viewer/2022102422/554a4ecfb4c90531228b4929/html5/thumbnails/52.jpg)
Spying With SinonStubs, Spies and Mock Objects explained
![Page 53: Unit Testing JavaScript Applications](https://reader037.vdocuments.mx/reader037/viewer/2022102422/554a4ecfb4c90531228b4929/html5/thumbnails/53.jpg)
Agenda• Reasons to mock
• Vanilla mocking
• How sinon can help
• Stubs and Spies
• Faking timers
• Faking the server
![Page 54: Unit Testing JavaScript Applications](https://reader037.vdocuments.mx/reader037/viewer/2022102422/554a4ecfb4c90531228b4929/html5/thumbnails/54.jpg)
Reasons To Mock
![Page 55: Unit Testing JavaScript Applications](https://reader037.vdocuments.mx/reader037/viewer/2022102422/554a4ecfb4c90531228b4929/html5/thumbnails/55.jpg)
Reasons To Mock
PersonalData$.ajax setTimeout
![Page 56: Unit Testing JavaScript Applications](https://reader037.vdocuments.mx/reader037/viewer/2022102422/554a4ecfb4c90531228b4929/html5/thumbnails/56.jpg)
Reasons To Mock
PersonalData$.ajax setTimeout
![Page 57: Unit Testing JavaScript Applications](https://reader037.vdocuments.mx/reader037/viewer/2022102422/554a4ecfb4c90531228b4929/html5/thumbnails/57.jpg)
Reasons To Mock
• PersonalData object can save data to server
• If saving failed, it retries 3 times
![Page 58: Unit Testing JavaScript Applications](https://reader037.vdocuments.mx/reader037/viewer/2022102422/554a4ecfb4c90531228b4929/html5/thumbnails/58.jpg)
Reasons To Mock
• Both server and clock are external
• We prefer to test in isolation
![Page 59: Unit Testing JavaScript Applications](https://reader037.vdocuments.mx/reader037/viewer/2022102422/554a4ecfb4c90531228b4929/html5/thumbnails/59.jpg)
What We Can Do
• Provide our own $.ajax, that won’t go to the server
• Provide our own setTimeout that won’t wait for the time to pass
![Page 60: Unit Testing JavaScript Applications](https://reader037.vdocuments.mx/reader037/viewer/2022102422/554a4ecfb4c90531228b4929/html5/thumbnails/60.jpg)
What We Can Do
• Lab: Given the class here https://gist.github.com/ynonp/6667146
• Write a test case to verify sendData actually retried 3 times
![Page 61: Unit Testing JavaScript Applications](https://reader037.vdocuments.mx/reader037/viewer/2022102422/554a4ecfb4c90531228b4929/html5/thumbnails/61.jpg)
What We Can Do
• Solution: https://gist.github.com/ynonp/6667284
![Page 62: Unit Testing JavaScript Applications](https://reader037.vdocuments.mx/reader037/viewer/2022102422/554a4ecfb4c90531228b4929/html5/thumbnails/62.jpg)
Mocking Notes
• Solution is far from perfect.
• After the test our “fake” methods remain
• Writing “fake” methods was not trivial
![Page 63: Unit Testing JavaScript Applications](https://reader037.vdocuments.mx/reader037/viewer/2022102422/554a4ecfb4c90531228b4929/html5/thumbnails/63.jpg)
This Calls for Sinon
![Page 64: Unit Testing JavaScript Applications](https://reader037.vdocuments.mx/reader037/viewer/2022102422/554a4ecfb4c90531228b4929/html5/thumbnails/64.jpg)
About Sinon
• A JS mocking library
• Helps create fake objects
• Helps tracking them
![Page 65: Unit Testing JavaScript Applications](https://reader037.vdocuments.mx/reader037/viewer/2022102422/554a4ecfb4c90531228b4929/html5/thumbnails/65.jpg)
About Sinon
• Homepage: http://sinonjs.org/
• Google Group: http://groups.google.com/group/sinonjs
• IRC Channel: #sinon.js on freenode
![Page 66: Unit Testing JavaScript Applications](https://reader037.vdocuments.mx/reader037/viewer/2022102422/554a4ecfb4c90531228b4929/html5/thumbnails/66.jpg)
Solving with Sinon
• Here’s how sinon might help us with the previous task
• Code: https://gist.github.com/ynonp/6667378
![Page 67: Unit Testing JavaScript Applications](https://reader037.vdocuments.mx/reader037/viewer/2022102422/554a4ecfb4c90531228b4929/html5/thumbnails/67.jpg)
Solution Notes
• Sinon’s fake timer was easier to use than writing our own
• Now we have a synchronous test (instead of async)
![Page 68: Unit Testing JavaScript Applications](https://reader037.vdocuments.mx/reader037/viewer/2022102422/554a4ecfb4c90531228b4929/html5/thumbnails/68.jpg)
Let’s Talk About Sinon
![Page 69: Unit Testing JavaScript Applications](https://reader037.vdocuments.mx/reader037/viewer/2022102422/554a4ecfb4c90531228b4929/html5/thumbnails/69.jpg)
Spies
• A spy is a function that provides the test code with info about how it was used
![Page 70: Unit Testing JavaScript Applications](https://reader037.vdocuments.mx/reader037/viewer/2022102422/554a4ecfb4c90531228b4929/html5/thumbnails/70.jpg)
Spies Demodescribe('Sinon', function() { describe('spies', function() { ! it('should keep count', function() { ! var s = sinon.spy(); s(); assert.isTrue(s.calledOnce); ! s(); assert.isTrue(s.calledTwice); ! s(); assert.equal(s.callCount, 3); ! }); }); });
![Page 71: Unit Testing JavaScript Applications](https://reader037.vdocuments.mx/reader037/viewer/2022102422/554a4ecfb4c90531228b4929/html5/thumbnails/71.jpg)
Spy On Existing Funcsdescribe('Sinon', function() { describe('spies', function() { ! it('should keep count', function() { var p = new PersonalData(); var spy = sinon.spy(p, 'sendData'); ! p.sendData(); ! assert.isTrue( spy.calledOnce ); }); }); });
![Page 72: Unit Testing JavaScript Applications](https://reader037.vdocuments.mx/reader037/viewer/2022102422/554a4ecfb4c90531228b4929/html5/thumbnails/72.jpg)
Spies Notes
• Full API: http://sinonjs.org/docs/#spies
• Tip: Use as callbacks
![Page 73: Unit Testing JavaScript Applications](https://reader037.vdocuments.mx/reader037/viewer/2022102422/554a4ecfb4c90531228b4929/html5/thumbnails/73.jpg)
Spy + Action = Stub
![Page 74: Unit Testing JavaScript Applications](https://reader037.vdocuments.mx/reader037/viewer/2022102422/554a4ecfb4c90531228b4929/html5/thumbnails/74.jpg)
Stub Demo
• Let’s fix our starting example
• We’ll replace $.ajax with a stub
• That stub always fails
![Page 75: Unit Testing JavaScript Applications](https://reader037.vdocuments.mx/reader037/viewer/2022102422/554a4ecfb4c90531228b4929/html5/thumbnails/75.jpg)
Stub Demovar stub = sinon.stub(jQuery, 'ajax').yieldsTo('error'); !describe('Data', function() { describe('#sendData()', function() { ! it('should retry 3 times before quitting', function() { var p = new PersonalData(); p.sendData(); assert.equal(stub.callCount, 1); }); }); });
![Page 76: Unit Testing JavaScript Applications](https://reader037.vdocuments.mx/reader037/viewer/2022102422/554a4ecfb4c90531228b4929/html5/thumbnails/76.jpg)
What Can Stubs Do
var callback = sinon.stub(); !callback.withArgs(42).returns(1); !callback.withArgs(1).throws("TypeError"); !
![Page 77: Unit Testing JavaScript Applications](https://reader037.vdocuments.mx/reader037/viewer/2022102422/554a4ecfb4c90531228b4929/html5/thumbnails/77.jpg)
Stubs API• Full Stubs API docs:
http://sinonjs.org/docs/#stubs
• Main actions:
• return stuff
• throw stuff
• call stuff
![Page 78: Unit Testing JavaScript Applications](https://reader037.vdocuments.mx/reader037/viewer/2022102422/554a4ecfb4c90531228b4929/html5/thumbnails/78.jpg)
Spies Lab
• Given code here: https://gist.github.com/ynonp/7101081
• Fill in the blanks to make the tests pass
![Page 79: Unit Testing JavaScript Applications](https://reader037.vdocuments.mx/reader037/viewer/2022102422/554a4ecfb4c90531228b4929/html5/thumbnails/79.jpg)
Fake Timers
• Use sinon.useFakeTimers() to create a fake timer
• Use clock.restore() to clear fake timers
![Page 80: Unit Testing JavaScript Applications](https://reader037.vdocuments.mx/reader037/viewer/2022102422/554a4ecfb4c90531228b4929/html5/thumbnails/80.jpg)
Fake Timers
• Use tick(...) to advance
• Affected methods:
• setTimeout, setInterval, clearTimeout, clearInterval
• Date constructor
![Page 81: Unit Testing JavaScript Applications](https://reader037.vdocuments.mx/reader037/viewer/2022102422/554a4ecfb4c90531228b4929/html5/thumbnails/81.jpg)
Fake Servers
• Testing client/server communication is hard
• Use fake servers to simplify it
![Page 82: Unit Testing JavaScript Applications](https://reader037.vdocuments.mx/reader037/viewer/2022102422/554a4ecfb4c90531228b4929/html5/thumbnails/82.jpg)
Fake Servers
PersonalData$.ajax
![Page 83: Unit Testing JavaScript Applications](https://reader037.vdocuments.mx/reader037/viewer/2022102422/554a4ecfb4c90531228b4929/html5/thumbnails/83.jpg)
Fake Servers
PersonalData$.ajax
Fake
![Page 84: Unit Testing JavaScript Applications](https://reader037.vdocuments.mx/reader037/viewer/2022102422/554a4ecfb4c90531228b4929/html5/thumbnails/84.jpg)
Let’s write a test for the following class
1. function Person(id) { 2. var self = this; 3. 4. self.load = function() { 5. var url = '/users/' + id; 6. 7. $.get('/users/' + id, function(info) { 8. self.name = info.name; 9. self.favorite_color = info.favorite_color; 10. }); 11. }; 12. }
![Page 85: Unit Testing JavaScript Applications](https://reader037.vdocuments.mx/reader037/viewer/2022102422/554a4ecfb4c90531228b4929/html5/thumbnails/85.jpg)
Testing Plan
• Set-up a fake server
• Create a new Person
• call load()
• verify fields data
![Page 86: Unit Testing JavaScript Applications](https://reader037.vdocuments.mx/reader037/viewer/2022102422/554a4ecfb4c90531228b4929/html5/thumbnails/86.jpg)
Setting Up The Server
1. var server = sinon.fakeServer.create(); 2. 3. var headers = {"Content-Type" : "application/json"}; 4. var response = JSON.stringify( 5. {"name" : "joe", "favorite_color": "blue" }); 6. 7. server.respondWith("GET", "/users/7", 8. [200, headers, response]); 9. // now requesting /user/info.php returns joe's info as a JSON
![Page 87: Unit Testing JavaScript Applications](https://reader037.vdocuments.mx/reader037/viewer/2022102422/554a4ecfb4c90531228b4929/html5/thumbnails/87.jpg)
Loading a Person
1. var p = new Person(7); 2. // sends a request 3. p.load(); 4. 5. // now we have 1 pending request, let's fake the response 6. server.respond();
![Page 88: Unit Testing JavaScript Applications](https://reader037.vdocuments.mx/reader037/viewer/2022102422/554a4ecfb4c90531228b4929/html5/thumbnails/88.jpg)
Verifying the Data
1. // finally, verify data 2. expect(p.name).to.eq('joe'); 3. expect(p.favorite_color).to.eq('blue'); 4. 5. // and restore AJAX behavior 6. server.restore();
![Page 89: Unit Testing JavaScript Applications](https://reader037.vdocuments.mx/reader037/viewer/2022102422/554a4ecfb4c90531228b4929/html5/thumbnails/89.jpg)
Fake Server
• Use respondWith() to set up routes
• Use respond() to send the response
![Page 90: Unit Testing JavaScript Applications](https://reader037.vdocuments.mx/reader037/viewer/2022102422/554a4ecfb4c90531228b4929/html5/thumbnails/90.jpg)
Fake Server• Regexps are also supported, so this works:
1. server.respondWith(/\/todo-items\/(\d+)/, function (xhr, id) { 2. xhr.respond( 3. 200, 4. { "Content-Type": "application/json" }, 5. '[{ "id": ' + id + ' }]'); 6. });
![Page 91: Unit Testing JavaScript Applications](https://reader037.vdocuments.mx/reader037/viewer/2022102422/554a4ecfb4c90531228b4929/html5/thumbnails/91.jpg)
Fake Server
• For fine grained control, consider fake XMLHttpRequest
• http://sinonjs.org/docs/#server
![Page 92: Unit Testing JavaScript Applications](https://reader037.vdocuments.mx/reader037/viewer/2022102422/554a4ecfb4c90531228b4929/html5/thumbnails/92.jpg)
Wrapping Up
![Page 93: Unit Testing JavaScript Applications](https://reader037.vdocuments.mx/reader037/viewer/2022102422/554a4ecfb4c90531228b4929/html5/thumbnails/93.jpg)
Wrapping Up
• Unit tests work best in isolation
• Sinon will help you isolate units, by faking their dependencies
![Page 94: Unit Testing JavaScript Applications](https://reader037.vdocuments.mx/reader037/viewer/2022102422/554a4ecfb4c90531228b4929/html5/thumbnails/94.jpg)
Wrapping Up
• Write many tests
• Each test verifies a small chunk of code
• Don’t test everything
![Page 95: Unit Testing JavaScript Applications](https://reader037.vdocuments.mx/reader037/viewer/2022102422/554a4ecfb4c90531228b4929/html5/thumbnails/95.jpg)
Online Resources• Chai:
http://chaijs.com/
• Mocha: http://visionmedia.github.io/mocha/
• Sinon: http://sinonjs.org/
• Karma (test runner): http://karma-runner.github.io/0.10/index.html
![Page 96: Unit Testing JavaScript Applications](https://reader037.vdocuments.mx/reader037/viewer/2022102422/554a4ecfb4c90531228b4929/html5/thumbnails/96.jpg)
Thanks For Listening
• Ynon Perek
• http://ynonperek.com