Jasmine
Testing Modules
You can test node modules and classes in Jasmine by using the module.exports
syntax combined with require
inside of your jasmine tests. In the myClass
file below, a class called MyClass
is defined using ES6 syntax. Then at the bottom of the class it is added to the module.exports
path.
// src/myClass.js
class MyClass {
constructor(name) {
this.name = name
}
sayName() {
return 'hello my name is ' + this.name
}
}
module.exports = MyClass
With MyClass
added to module.exports
it can now be loaded inside a Jasmine test using require
and the relative file path from the test to the source file that is require
d. This class can be instantiated inside the beforeEach
function as with any class that you might load into the Jasmine SpecRunner.html
.
// spec/myClassSpec.js
describe('My Class', function() {
var MyClass = require('../src/myClass') // load MyClass from the myClass.js file
var myClassInstance
beforeEach(function() {
myClassInstance = new MyClass('Dec')
})
describe('sayName', function() {
it('says the hello' function() {
expect(myClassInstance.sayName()).toEqual('hello my name is Dec')
})
})
})
Spies
The Jasmine equivalent of a doubles and mocks are spies. These have the same functionality of stubbing methods, receiving calls and having pre-defined returns.
Spy Objects
You can create a spy object using the creatSpyObject
method and then submitting the name of the object that spy describes and an array of strings which represent the methods that the spy object can receive. In the example below the mySpy
object that is passed to any other code will respond to the greet method.
mySpy = jasmine.createSpyObject('spy', ['greet'])
You can check that method on a spy object has been called by using the toHaveBeenCalled
method.
it('calls the greet method', function() {
// code that calls the greet function from the tested object
expect(mySpy.greet).toHaveBeenCalled()
});
You can check that a specific argument was passed in with the spy objects method called by using the toHaveBeenCalledWith
function and submitting an argument which describes the expected input.
it('calls the greet method', function() {
// code that calls the greet function and passes in an argument from the tested object
expect(mySpy.greet).toHaveBeenCalledWith('Dec');
});
You can define a return type for spy object methods using the .and.returnValue
function.
it('returns an expected value', function() {
mySpy.greet.and.returnValue(true)
expect(mySpy.greet()).toBe(true)
});
Stubbing
You can stub methods on a real object with a pre-defined return type by using the spyOn
method combined with the .and.returnValue
function. In the example below the random
method of the Math
object is stubbed to always return 203
.
it('makes Math random return 203', function() {
spyOn(Math, 'random').and.returnValue(203)
expect(Math.random()).toEqual(203)
});
You cannot directly use the toHaveBeenCalled
function on a real object you must stub it first. To check that a stubbed method was called use the spyOn
syntax in conjunction with the toHaveBeenCalled
method.
it('call the random method on page', function() {
spyOn(Math, 'random')
// code that calls Math.random in some capacity
expect(Math.random).toHaveBeenCalled()
});
You can stub a method and make it return its real return value using the .and.callThrough
method. If you just spyOn
on an object’s function it will not return anything.
it('stubs the function while maintaining the return value', function() {
obj = { myFunction: function() { return 10 } }
spyOn(obj, 'myFunction').and.callThrough()
expect(obj.myFunction()).toEqual(10)
});
You can stub and spyOn
the class prototype
methods in the same manner as above. This allows you to pass in constructor (class) functions to an object. By then stubbing the function property in the prototype
of a function all instances of that class will have a stubbed instance method.
it('stubs a prototype function', function() {
aClass = function() {}
aClass.prototype.instanceFunction = function() {}
aClassInstance = new aClass();
spyOn(aClass.prototype, 'instanceFunction').and.returnValue(10);
expect(aClassInstance.instanceFunct()).toEqual(10);
});
Testing Async Code
You can test asynchronous code and requests using the async
and await
keywords. You must pass an async
method into the jasmine it
block so that it can use await
to coerce the result of the asynchronous request into a variable that can then be tested.
it('tests an asynchronous method', async function() {
const result = await someAsyncFunctionThatReturnsAPromise()
expect(result).toEqual(expectation)
})