Jasmine unit testing tutorial with examples

Jasmine is one of the popular JavaScript unit testing frameworks which is capable of testing synchronous and asynchronous JavaScript code. It is used in BDD (behavior-driven development) programming which focuses more on the business value than on the technical details. In this Jasmine tutorial, we will learn Jasmine framework in detail from setup instructions to understanding output of testcases.

1. Jasmine Setup Configuration

First download jasmine framework and extract it inside your project folder. I will suggest to create a separate folder /jasmine under /js or /javascript folder which may be already present in your application.

You will get below four folders/files in distribution bundle:

/src : contains the JavaScript source files that you want to test

/lib : contains the framework files

/spec : contains the JavaScript testing files

SpecRunner.html : is the test case runner HTML file

You may delete /src folder; and reference the source files from their current location inside SpecRunner.html file. The default file looks like below, and you will need to change the files included from /src and /spec folders.

2. Jasmine Suite and Specs

In Jasmine, there are two important terms – suite and spec.

2.1. Suite

A Jasmine suite is a group of test cases that can be used to test a specific behavior of the JavaScript code (a JavaScript object or function). This begins with a call to the Jasmine global function describe with two parameters – first parameter represents the title of the test suite and second parameter represents a function that implements the test suite.

//This is test suite
describe("Test Suite", function() {
//.....
});

2.2. Spec

A Jasmine spec represents a test case inside the test suite. This begins with a call to the Jasmine global function it with two parameters – first parameter represents the title of the spec and second parameter represents a function that implements the test case.

In practice, spec contains one or more expectations. Each expectation represents an assertion that can be either true or false. In order to pass the spec, all of the expectations inside the spec have to be true. If one or more expectations inside a spec is false, the spec fails.

Let’s start writing unit tests for MathUtils.js to better understand suite and specs. We will write these specs in spec/MathUtils.js.

describe("MathUtils", function() {
var calc;
//This will be called before running each spec
beforeEach(function() {
calc = new MathUtils();
});
describe("when calc is used to peform basic math operations", function(){
//Spec for sum operation
it("should be able to calculate sum of 3 and 5", function() {
expect(calc.sum(3,5)).toEqual(8);
});
//Spec for multiply operation
it("should be able to multiply 10 and 40", function() {
expect(calc.multiply(10, 40)).toEqual(400);
});
//Spec for factorial operation for positive number
it("should be able to calculate factorial of 9", function() {
expect(calc.factorial(9)).toEqual(362880);
});
//Spec for factorial operation for negative number
it("should be able to throw error in factorial operation when the number is negative", function() {
expect(function() {
calc.factorial(-7)
}).toThrowError(Error);
});
});
});

On opening the SpecRunner.html file in browser, specs are run and result is rendered in browser as shown below:

Jasmine Output

3. Setup and Teardown

For setup and tear down purpose, Jasmine provides two global functions at suite level i.e. beforeEach() and afterEach().

3.1. beforeEach()

The beforeEach function is called once before each spec in the describe() in which it is called.

3.2. afterEach()

The afterEach function is called once after each spec.

In practice, spec variables (is any) are defined at the top-level scope — the describe block — and initialization code is moved into a beforeEach function. The afterEach function resets the variable before continuing. This helps the developers in not to repeat setup and finalization code for each spec.

4. Jasmine Describe Blocks

In Jasmine, describe function is for grouping related specs. The string parameter is for naming the collection of specs, and will be concatenated with specs to make a spec’s full name. This helps in finding specs in a large suite.

Good thing is, you can have nested describe blocks as well. In case of nested describe, before executing a spec, Jasmine walks down executing each beforeEach function in order, then executes the spec, and lastly walks up executing each afterEach function.

Let’s understand it by an example. Replace the content in MathUtilSpecs.js will following code:

I will suggest you to place more specs in above code, and check out the execution flow for more better understanding.

5. Jasmine Matchers

In first example, we saw the usage of toEqual and toThrow function. They are matchers and use to compare the actual and expected outputs of any jasmine test. Thy are just like java assertions – if it may help you.

Let’s list down all such Jasmine matchers which can help you more robust and meaningful test specs.

Matcher

Purpose

toBe()

passed if the actual value is of the same type and value as that of the expected value. It compares with === operator

toEqual()

works for simple literals and variables;should work for objects too

toMatch()

to check whether a value matches a string or a regular expression

toBeDefined()

to ensure that a property or a value is defined

toBeUndefined()

to ensure that a property or a value is undefined

toBeNull()

to ensure that a property or a value is null.

toBeTruthy()

to ensure that a property or a value is true

ToBeFalsy()

to ensure that a property or a value is false

toContain()

to check whether a string or array contains a substring or an item.

toBeLessThan()

for mathematical comparisons of less than

toBeGreaterThan()

for mathematical comparisons of greater than

toBeCloseTo()

for precision math comparison

toThrow()

for testing if a function throws an exception

toThrowError()

for testing a specific thrown exception

The Jasmine not keyword can be used with every matcher’s criteria for inverting the result. e.g.

6. Disable Suites and Specs

Many times, for various reasons, you may want to disable suites – for some time. In this case, you need not to remove the code – rather just add char x in start of describe to make if xdescribe.

These suites and any specs inside them are skipped when run and thus their results will not appear in the results.

xdescribe("MathUtils", function() {
//code
});

In case, you do not want to disable whole suite and rather want to disable only a certain spec test, then put the x before that spec itself and this time only this spec will be skipped.

describe("MathUtils", function() {
//Spec for sum operation
xit("should be able to calculate the sum of two numbers", function() {
expect(10).toBeSumOf(7, 3);
});
});

7. Working with Jasmine Spies

Jasmine has test double functions called spies. A spy can stub any function and tracks calls to it and all arguments. A spy only exists in the describe or it block in which it is defined, and will be removed after each spec. To create a spy on any method, use spyOn(object, 'methodName') call.

There are two matchers toHaveBeenCalled and toHaveBeenCalledWith which should be used with spies. toHaveBeenCalled matcher will return true if the spy was called; and toHaveBeenCalledWith matcher will return true if the argument list matches any of the recorded calls to the spy.

Above example is very much most basic in nature, you can use spies to verify the calls for internal methods as well. E.g. If you call method calculateInterest() on any object then you may want to check if getPrincipal(), getROI() and getTime() must have been called inside that object. Spy will help you verify these kind of assumptions.

When there is not a function to spy on, jasmine.createSpy can create a bare spy. This spy acts as any other spy – tracking calls, arguments, etc. But there is no implementation behind it. Spies are JavaScript objects and can be used as such. Mostly, these spies are used as callback functions to other functions where it is needed.

Every call to a spy is tracked and exposed on the calls property. Let’s see how we can use these properties to track the spy.

Tracking Property

Purpose

.calls.any()

returns false if the spy has not been called at all, and then true once at least one call happens.

.calls.count()

returns the number of times the spy was called

.calls.argsFor(index)

returns the arguments passed to call number index

.calls.allArgs()

returns the arguments to all calls

.calls.all()

returns the context (the this) and arguments passed all calls

.calls.mostRecent()

returns the context (the this) and arguments for the most recent call

.calls.first()

returns the context (the this) and arguments for the first call

.calls.reset()

clears all tracking for a spy

8. Jasmine tutorial – final thoughts

Jasmine is very capable framework for testing javascript functions, but learning curve is little bit difficult. It will require a great amount of discipline in writing actual javascript code – before it could be tested with Jasmine effectively.

And remember that Jasmine is intended to be used for writing tests in BDD (Behavior-driven development) style. Do not misuse it by testing irrelevant things.

About Lokesh Gupta

Founded HowToDoInJava.com in late 2012. I love computers, programming and solving problems everyday. A family guy with fun loving nature. You can find me on Facebook, Twitter and Google Plus.

Feedback, Discussion and Comments

Steve Py

July 21, 2017

Excellent work! I wish that the people that develop these frameworks and such would take the effort to give meaningful examples like you have done to explain the ways their libraries can be used. (not to mention keeping them up to date) Seeing examples where they just writes a trivial block of javascript code inside an it() function without demonstrating how best to structure a test around an actual Javascript function/class you want tested isn’t very encouraging. Nice work outlining how the Jasmine test features can be set up around the stuff I’d expect to test.

I’m curios how you would run the tests in the command line without the help of the html script tags, is it still possible to run the jasmine command in the commandline? How does it import the javascript files without the html?

Hi, if i want to stop execution of suits on any one test case fails, or if first case fails then i want to stop execution of spec means i do not want remaining test to run. What is the way to achieve that?

I currently have an issue where I’m trying to test whether internal methods of a void method have been called. You briefly mention that you can use spies to verify the calls for internal methods, but can you give an example of how to do this? My spy for the external method passes, but when I try to call the internal methods I get an error: