-
Data type test patterns
-
Method use
-
Mock $http calls
-
Have a good pattern?
Example implementation of these testing patterns
####Suggested Service Unit Test Setup ↑
# CoffeeScript
describe 'Service: mySvc', ->
mySvc = null
httpBackend = null
mockData = null
# Use to provide any mocks needed
_provide = (callback) ->
# Execute callback with $provide
module ($provide) ->
callback $provide
# Make sure CoffeeScript doesn't return anything
null
# Use to inject the code under test
_inject = ->
inject (_mySvc_, $httpBackend, _mockData_) ->
mySvc = _mySvc_
httpBackend = $httpBackend
mockData = _mockData_
# make sure no expectations were missed in your tests.
# (e.g. expectGET or expectPOST)
afterEach ->
httpBackend.verifyNoOutstandingExpectation()
httpBackend.verifyNoOutstandingRequest()
# Call this before each test, except where you are testing for errors
_setup = ->
# Mock any expected data
_provide (provide) ->
provide.value 'myVal', {}
# Inject the code under test
_inject()
beforeEach ->
# Load the service's module
module 'myApp','myApp.mockData'
describe 'the service api', ->
beforeEach ->
# Inject with all expected values
_setup()
it 'should exist', ->
expect(!!mySvc).toBe true
# Add specs
describe 'service errors', ->
it 'should throw an error when required dependency is missing', ->
# Use an anonymous function to wrap the code that will fail
wrapper = ->
# Inject WITHOUT providing required values
_inject()
expect(wrapper).toThrow 'mySvc: myVal not provided'
###
Note: you can use Function.bind to avoid an anonymous function wrapper for inject,
however, you'll need a polyfill for PhantomJS such as: http://goo.gl/XSLOdx
svc = (mySvc) ->
expect(inject.bind(null, svc)).toThrow 'mySvc: myVal not provided'
###
// JavaScript
describe('Service: mySvc', function () {
var mySvc, httpBackend, mockData;
// Use to provide any mocks needed
function _provide(callback) {
// Execute callback with $provide
module(function ($provide) {
callback($provide);
});
}
// Use to inject the code under test
function _inject() {
inject(function (_mySvc_, $httpBackend, _mockData_) {
mySvc = _mySvc_;
httpBackend = $httpBackend;
mockData = _mockData_;
});
}
// Call this before each test, except where you are testing for errors
function _setup() {
// Mock any expected data
_provide(function (provide) {
provide.value('myVal', {});
});
// Inject the code under test
_inject();
}
beforeEach(function () {
// Load the service's module
module('myApp', 'myApp.mockData');
});
// make sure no expectations were missed in your tests.
// (e.g. expectGET or expectPOST)
afterEach(function () {
httpBackend.verifyNoOutstandingExpectation();
httpBackend.verifyNoOutstandingRequest();
});
describe('the service api', function () {
beforeEach(function () {
// Inject with expected values
_setup();
});
it('should exist', function () {
expect(!!mySvc).toBe(true);
});
// Add specs
});
describe('service errors', function () {
it('should throw an error when required dependency is missing', function () {
// Use an anonymous function to wrap the code that will fail
function wrapper() {
// Inject WITHOUT providing required values
_inject();
}
expect(wrapper).toThrow('mySvc: myVal not provided');
/*
Note: you can use Function.bind to avoid an anonymous function wrapper for inject,
however, you'll need a polyfill for PhantomJS such as: http://goo.gl/XSLOdx
var svc = function (mySvc) {};
expect(inject.bind(null, svc)).toThrow('mySvc: myVal not provided');
*/
});
});
});
####My service should:
#####provide a myThing
property ↑
# CoffeeScript
it 'should define a myThing property', ->
expect(mySvc.myThing).toBeDefined()
// JavaScript
it('should define a myThing property', function () {
expect(mySvc.myThing).toBeDefined();
});
#####provide a myArray
property ↑
# CoffeeScript
it 'should provide a myArray property', ->
expect(mySvc.myArray instanceof Array).toBe true
// JavaScript
it('should provide a myArray property', function () {
expect(mySvc.myArray instanceof Array).toBe(true);
});
#####provide a myBoolean
property ↑
# CoffeeScript
it 'should provide a boolean myBoolean property', ->
expect(typeof mySvc.myBoolean).toBe 'boolean'
// JavaScript
it('should provide a boolean myBoolean property', function () {
expect(typeof mySvc.myBoolean).toBe('boolean');
});
#####provide a myDate
property ↑
# CoffeeScript
it 'should provide a myDate property', ->
expect(mySvc.myDate instanceof Date).toBe true
// JavaScript
it('should provide a myDate property', function () {
expect(mySvc.myDate instanceof Date).toBe(true);
});
#####provide a myMethod
function ↑
# CoffeeScript
it 'should provide a myMethod function', ->
expect(typeof mySvc.myMethod).toBe 'function'
// JavaScript
it('should provide a myMethod function', function () {
expect(typeof mySvc.myMethod).toBe('function');
});
#####provide a myNull
property ↑
# CoffeeScript
it 'should provide a myNull property', ->
expect(mySvc.myNull).toBe null
// JavaScript
it('should provide a myNull property', function () {
expect(mySvc.myNull).toBe(null);
});
#####provide a myNumber
property ↑
# CoffeeScript
it 'should provide a myNumber property', ->
expect(typeof mySvc.myNumber).toBe 'number'
// JavaScript
it('should provide a myNumber property', function () {
expect(typeof mySvc.myNumber).toBe('number');
});
#####provide a myObject
property ↑
# CoffeeScript
it 'should provide a myObject property', ->
expect(mySvc.myObject instanceof Object).toBe true
// JavaScript
it('should provide a myObject property', function () {
expect(mySvc.myObject instanceof Object).toBe(true);
});
#####provide a myRegExp
property ↑
# CoffeeScript
it 'should provide a myRegExp property', ->
expect(mySvc.myRegExp instanceof RegExp).toBe true
// JavaScript
it('should provide a myRegExp property', function () {
expect(mySvc.myRegExp instanceof RegExp).toBe(true);
});
#####provide a myString
property ↑
# CoffeeScript
it 'should provide a myString property', ->
expect(typeof mySvc.myString).toBe 'string'
// JavaScript
it('should provide a myString property', function () {
expect(typeof mySvc.myString).toBe('string');
});
#####expect myUndefined
to be undefined ↑
# CoffeeScript
it 'should expect myUndefined to be undefined', ->
expect(mySvc.myUndefined).not.toBeDefined()
// JavaScript
it('should expect myUndefined to be undefined', function () {
expect(mySvc.myUndefined).not.toBeDefined();
});
#####myMethod
should return expected value ↑
# CoffeeScript
it 'myMethod should return expected value', ->
result = mySvc.myMethod()
expect(result).toBe('Not implemented')
// JavaScript
it('myMethod should return expected value', function () {
var result = mySvc.myMethod();
expect(result).toBe('Not implemented');
});
#####getData
should make $http call and return value ↑
# CoffeeScript
it 'getData should return make $http call', ->
data = null
#given
httpBackend.whenGET 'http://www.mocky.io/v2/553e0de62f711b7b1aa5d24f'
.respond(mockData)
#when
mySvc.getData()
.then (response) ->
data = response.data
httpBackend.flush()
#then
expect(data.map( (elm) ->
elm.first_name
)).toEqual mockData.data.map( (elm) ->
elm.first_name
)
// JavaScript
it('getData should make $http call', function () {
var data;
//given
httpBackend.whenGET('http://www.mocky.io/v2/553e0de62f711b7b1aa5d24f').respond(mockData);
//when
mySvc.getData().then(function (response) {
data = response.data;
});
httpBackend.flush();
//then
expect(data.map(function (elm) {return elm.first_name; })).toEqual(mockData.data.map(function (elm) {return elm.first_name; }));
});