javascript unit test with angular 1.x (course exercise)
Reference for angular unit testing course.
Motivation
script “compile”
Our javascript code never gets compiled, hence we are open to a lot of runtime errors..
testable code === modular code
When we write with angular, we often mistake with our module separation.
angular.module('a', [])
.service('ServiceA', function() {
this.getName = function() {
return 'bob';
}
});
angular.module('b', [])
.service('ServiceB', ['ServiceA', function(ServiceA) {
this.greet = function() {
return 'Hello ' + ServiceA.getName()
}
}]);
angular.module("app", ['a', 'b'])
.controller("myCtrl", function($scope, ServiceB) {
$scope.data = ServiceB.greet();
});
very fast
Yes. Javascript unit testing is much faster than the alternative, slow UI testing..
jasmine
jasmine introduction
Check out jasmine docs
test a javascript function
test a javascript object
TODO: fix this test.
testable code
How can we test this?
var Greeter = function() {
function greet(name) {
//TODO this is complex code
console.log("Hello " + name);
}
this.greet = greet;
};
jasmine spies
spyOn
dependency injection?
How can we test this?
var LastNameService = function() {
this.getLastName = function(firstName) {
switch (firstName) {
case "Bob":
return "Marley";
case "Phill":
return "Collins";
}
}
};
var Greeter = function() {
var dataService = new LastNameService();
this.greet = function greet(name) {
return "Hello " + name + " " + dataService.getLastName(name);
};
};
spyOn and return
TODO: fix this test.
createSpyObj
TODO: fix this test.
angular + jasmine
ngMock
See docs
- angular.mock.module
- angular.mock.inject
testing services
simple service test
TODO: fix this test.
service test with spyOn
TODO: fix this test.
testing services with real DI
service with inject(spyOn)
$provide
See docs
service with real DI (createSpyObj)
TODO: fix this test.
testing controllers
use $controller - controllers are NOT singleton
stateless controller (controller as)
describe("MyController test suite", function() {
var ctrl;
beforeEach(module('MyModule'));
beforeEach(inject(function($controller) {
ctrl = $controller("MyController");
}));
it("should greet corretly", function() {
expect(ctrl.greet()).toBe('Hello Bob');
});
});
controller as (state on this)
TODO: fix this test.
controller with $scope (state on scope)
TODO: fix this test.
controller with DI
Now try to solve previous example with createSpyObj.
solution
testing directives
- use $compile
- test element - use jqlite selectors test
directive using scope + $watch
TODO: fix this test.
testing components (angular 1.5+)
- use
$componentController
to test the controller - use
$compile
to test element, like a directive
and what about testing lifecycle hooks?
Other angular patterns
test a controller using $http
use
$httpBackend
and don’t forget$httpBackend.flush()
TODO: write a test for the second scenario.
test a controller using $timeout
don’t forget
$timeout.flush()
TODO: Write a test for this controller.
test a controller using events
TODO: Write a test for this controller.
test a controller using promise
angular docs: “it’s important to know that the resolution of promises is tied to the digest cycle”
TODO: write a test for the second scenario.
Finally
Test writing challenge