Unit Testing in JavaScript with MVC and QUnit Lars Thorup ZeaLake Software Consulting June 14, 2011
May 07, 2015
Unit Testing in JavaScript with MVC and QUnitLars ThorupZeaLake Software Consulting
June 14, 2011
Who is Lars Thorup?● Software developer
● Coach: Automated testing and other agile practices
● Advisor: Assesses software projects and companies
● Founder and CEO of BestBrains and ZeaLake
Agenda● Sample application under test
● How to use QUnit
● Asynchronuous testing
● How to use Model-View-Controller
● Assumes knowledge about JavaScript
● Assumes knowledge about unit testing
JavaScript must be tested in the browser
Example app: Collaborative Dialog● Front end entirely in JavaScript
● Back end service methods implemented in C#
How do tests look like?● util.test.html
● ok(actual, message)
● equal(actual, expected, message)
● same(actual, expected, message)● deep equivalence
● raises(expected, function, message)
How to modularize tests?● view.test.html
● module(name, fixture)
● all following tests will have this being a newly created fixture object with setup() and teardown() run before and after the test
Testing ajax● svc.test.html
● call expect(number-of-assertions) to verify that callbacks was actually called
● call stop(timeout) before first ajax call
● call start() when test is complete● typically inside ajax callback
● if more than one asynchronous call in one test:● call stop() before each ● call start() in callback of each
Make your JavaScript testable
● MVC design pattern: Model - View - Controller
● Dependency injection
● Isolated testing controller
view model
svc
View● view.js
● injected html● load html page from the server● html becomes directly stylable
● Responsibilities● manipulate html● generate html from templates● dispatch events to listeners● nothing more!
● References● a set of event listeners
(typically the controller)
controller
view model
svc
Controller● controller.js
● Responsibilities● handle all events from the
view● poll model for change events if
relevant● convert events to commands
against the model● repaint strategy● error handling strategy
● References● the model (to execute
commands, polling)● the view (to do repainting)
controller
view model
svc
Model● model.js
● Responsibilities● cache state to minimize round
trips● provide view and controller
with a useful interface of the data model
● References● the service proxy
controller
view model
svc
Service Proxy● svc.js
● Responsibilities● provide a javascript api
mapping of the server api
● References● the physical server via ajax
controller
view model
svc
Testing the view● view.test.js
● Inject● controllerStub● canvas
● Invoke methods
● Assert● canvas● controllerStub
controllerStub
view
test
Testing the controller● controller.test.js
● Inject● viewStub● modelStub
● Invoke methods
● Assert● viewStub● modelStub
controller
viewStub modelStub
test
Testing the model● model.test.js
● Inject● serverStub
● Invoke methods
● Assert● state● serverStub
model
svcStub
test
Testing the service proxy● svc.test.js
● Invoke methods
● Assert● results
svc
test
Callbacks in JavaScript● Ajax means asynchronous
● Server methods become asynchronous● Model methods become asynchronous● To return a value you must supply a callback
● Error handling● Include in every callback
this in JavaScript● Avoid using this in callbacks, since this probably refers to
the object that invokes the callback, not the object that contains the code for the callback.
● Instead use jQuery's $proxy() method● Example: controller.js
Bootstrap● bootstrap() function
● see collabForm.js
● creates model, view and controller and ties them together
● start polling engine (if relevant)
● called by onload or $(document).ready()● see Index.aspx
Run tests on build server● QUnit tests needs to run in a browser
● On WIndows, the browser requires a WinStation● So the build server must be logged on at all times for this to work
● Hard to avoid tests that hang
● Consider running tests manually instead
Testing the backend● Test your webservices
● Use QUnit and assert on the returned JSON● Or use your backend testing tool
Real World Example● WizerPro, in JavaScript, using MVC pattern
Further reading● Documentation
● http://docs.jquery.com/Qunit
● Book● "Test-Driven JavaScript Development", Christian Johansen
● QUnit Presentation● http://benalman.com/talks/unit-testing-qunit.html
Future meetups● TDD coding dojo with C++ and Ruby
● Thursday June 24th (in a week!)
Feedback● Give your evaluation at meetup.com