Basic Introduction of JavaScript Testing Framework Jasmine
The basic of Jasmine is already discussed in my earlier blog. To read it please click here.
Spying with Jasmine
One of the basic reason of spying is to do unit testing of method in isolation. So we mock the method to bypass other dependencies.
Let's see what Jasmine offer us.
Spy on a method
spyOn(object, methodName)
it can only exist inside the describe
or it
block. In another words it can only be define inside spec or suit, and it will be removed once spec get existed. spyOn(obj , 'setName');
When you want to invoke the actual method but call will be tracked.
spyOn(obj , 'setName').and.callThrough();
When you call
and.callThrough
, the spy acts as a proxy, calling the real function, but passing through a spy object allowing you to add tests like expectation.
When you want to remove the effect of spyOn(obj , 'setName').and.callThrough()
spyOn(obj , 'setName').and.stub()
removes the effect ofspyOn(obj , 'setName').and.callThrough()
on a spy.
When you want to return a specific value on all calls.
spyOn(obj, "getName").and.returnValue('Andy');
When you want to invoke a custom function.
spyOn(obj, "getName").and.callFake(function(arguments, here) {
return 'Andy';
});
When you want to throw specific error.
spyOn(obj, "setName").and.throwError("myError");
Every call to a spy is tracked and exposed on the calls
property.
Calls | Purpose |
---|---|
any() |
returns false if the spy has not been called at all, and then true once at least one call happens. expect(obj.setName.calls.any()).toEqual('Andy'); |
count() |
returns the number of times the spy was called. expect(obj.setName.calls.count()).toEqual(2); |
argsFor(index) |
returns the arguments passed to call number index .
obj.setName('Andy');
expect(obj.setName.calls.argsFor(0)).toEqual(["Andy"]);
|
allArgs() |
returns the arguments to all calls.
obj.setName('Andy'); obj.setName('Anindya','Banerjee'); expect(obj.setName.calls.allArgs()).toEqual([["Andy"],["Anindya","Banerjee"]]); |
all() |
returns the context (the this ) and arguments passed all calls.
obj.setName('Andy'); expect(obj.setName.calls.all()).toEqual({object: obj, args: ["Andy"]}); |
mostRecent() |
returns the context (the this ) and arguments for the most recent call.
obj.setName('Andy'); obj.setName('Anindya','Banerjee'); expect(obj.setName.calls.mostRecent()).toEqual({object: obj, args:"Anindya","Banerjee"}); |
first() |
returns the context (the this ) and arguments for the first call.
obj.setName('Andy'); obj.setName('Anindya','Banerjee'); expect(obj.setName.calls.first()).toEqual({object: obj, args:"Andy"}); |
reset()
clears all tracking for a spy.
obj.setName.calls.reset();
There is a property named
object
which actually return the this
object when the spy was call. This can be used with all
/mostReset
/first
.Please note here these methods are return an array of json object and one of key is
object
. Please refer to the above table.Here is an example.
obj.setName('Andy');
obj.setName('Anindya','Banerjee');
expect(obj.setName.calls.all().object).toEqual(obj);
expect(obj.setName.calls.mostRecent().object).toEqual(obj);
expect(obj.setName.calls.first().object).toEqual(obj);
There are three matchers
toHaveBeenCalled
, toHaveBeenCalledWith
and toHaveBeenCalledTimes.
toHaveBeenCalled
return true
if the spy was called.
expect(obj.setName).toHaveBeenCalled();
toHaveBeenCalledWith
return true
if the argument list matches any of the recorded calls to the spy.
expect(obj.setName).toHaveBeenCalledWith('Andy');
toHaveBeenCalledTimes
return true
if the spy was called the specified number of times.
expect(obj.setName).toHaveBeenCalledTimes(2);
What we will do if we didn't have a function to spy on ?
Jasmine provide functions to deal with this kind of situations.
Function | Purpose |
---|---|
jasmine.createSpy |
create a spy function which doesn't exist.var dummyFunction = jasmine.createSpy('dummy function');
$('#mybutton').click(dummyFunction);
|
jasmine.createSpyObj |
create multiple spy function which doesn't exist.
// Suppose you got a Json object from back-end
// Person is a spy object with getName and getAge methods and an id property
var person = jasmine.createSpyObj("person", ["getName", "getAge"]);
person.id = 1234;
|
jasmine.any |
returns true if the constructor matches the constructor of the actual value.expect({}).toEqual(jasmine.any(Object)); expect(12).toEqual(jasmine.any(Number)); |
jasmine.anything |
returns true if the actual value is not null or undefined .
expect({}).toEqual(jasmine.anything());
|
jasmine.objectContaining
|
when an expectation only cares about certain key/value pairs in the actual.
var person = {
firstName : "Anindya",
lastName : "Banerjee",
aliasName : "Andy"
};
expect(person).toEqual(jasmine.objectContaining({ aliasName: "Andy" }));
|
jasmine.arrayContaining
|
when an expectation only cares about some of the values in an array.
var num = [1, 2, 3, 4];
expect(num).toEqual(jasmine.arrayContaining([3, 1]));
expect(num).not.toEqual(jasmine.arrayContaining([6]));
|
jasmine.stringMatching
|
When match a portion of a string in a spy expectation.
expect({names: 'AndyAnindya'}).toEqual({names: jasmine.stringMatching('Andy')});
|