npm install –g yo (for install yomen)
Step 3
npm install –g bower (for install bower)
Step 4
npm install –g generator-jasmine jasmine-core (for install jasmine)
The –g switch asked npm to install packages within node.js global modules directory. For finalize testing environment, we need to scaffold Jasmine’s Test directory. For this go to the your project location path and then run the below command. This command create a test directive and within that directive create a index.html file and a spec folder for storing the spec related js file within that directive. The index.html file is test runner or spec runner file of the jasmine.
Step 5
yo jasmine,
There is another way of using jasmine. For it, we can install karma framework using npm by using the below command.
npm install –g karma karma-cli jasmine-core
Now after it, go the project directory by browsing and initialize the configuration. For this karma ask few simple questions and on the basis of given answer it will create the configuration files.
karma init jasmine.config.js
After completing the configuration file creation, we just need to start the karma by passing the configuration file name as arguments.
karma start jasmine.config.js
Now, the environment for runt the jasmine test has been ready. Now, need to run the jasmime test. For this, We create a folder named test within the project directive and add one html file called index.html for running the jasmine test file. Now first we will create a simple JavaScript function which takes two number arguments and return the total of two numbers. For this, we need to add another JavaScript file within the same folder named sampletest.js and write down the below code –
Also, we need to another JavaScript file for write down the code of unit test. For this, we add another js file test.js and write down the below code. In this file, we add two scenarios. One for correct scenario and another is wrong scenario i.e. expect and given data does not match.
Now we add the below code in the index.html file.
When I write unit tests, I follow a pattern called arrange/act/assert (A/A/A). Arrange refers to the process of setting up the scenario required for the test. Act refers to performing the test itself, and assert refers to checking the result to make sure it is correct. Jasmine tests are written using JavaScript functions, which makes writing tests a nice extension of writing application code. There are several Jasmine functions in the example, which I have described below.
Name | Descriptions |
describe | Groups a number of related tests (this is optional, but it helpsorganize test code) |
beforeEach | Executes a function before each test (this is often used for thearrange part of a test) |
it | Executes a function to form a test (the act part of the test) |
expect | Identifies the result from the test (part of the assert stage) |
toEqual | Compares the result from the test to the expected value (the otherpart of the assert) |
The basic sequence to pay attention to is that the it function executes a test function so that the expect and toEqual functions can be used to assess the result. The toEqual function is only one way that Jasmine can evaluate the result of a test. I have listed the other available functions as below.
Name | Descriptions |
expect(x).toEqual(val) | Asserts that x has the same value as val (but not necessarily the same object) |
expect(x).toBe(obj) | Asserts that x and obj are the same object |
expect(x).toMatch(regexp) | Asserts that x matches the specified regular expression |
expect(x).toBeDefined() | Asserts that x has been defined |
expect(x).toBeUndefined() | Asserts that x has not been defined |
expect(x).toBeNull() | Asserts that x is null |
expect(x).toBeTruthy() | Asserts that x is true or evaluates to true |
expect(x).toBeFalsy() | Asserts that x is false or evaluates to false |
expect(x).toContain(y) | Asserts that x is a string that contains y |
expect(x).toBeGreaterThan(y) | Asserts that x is greater than y |
For perform a simple unit test, I first write down a simple JavaScript function which add two numbers :-
- function addNumber(x, y) {
- return x + y;
- }
Now, I add a spec file called index.html and write down the below code,
- <!doctype html>
- <html>
- <head>
- <title>Jasmine Spec Runner</title>
- <link href="../test_resource/jasmine.css" rel="stylesheet" />
- </head>
- <body>
- <script src="../test_resource/jasmine.js"></script>
- <script src="../test_resource/jasmine-html.js"></script>
- <script src="../test_resource/boot.js"></script>
- <script src="../CodeJs/sampleTest.js"></script>
-
- <script src="spec/test.js"></script>
- </body>
- </html>
Now, I will add the another js file to write down the unit test code as below,
- (function () {
- 'use strict';
-
- describe('addNumber Correct', function () {
- it('should return values', function () {
- var x = 10;
- var y = 20;
- var z = x + y;
- expect(addNumber(x, y)).toEqual(z);
- });
- });
-
- describe('addNumber Incorrect', function () {
- it('should return Incorrect values', function () {
- var x = 1;
- var y = 20;
- var z = x + y;
- expect(addNumber(x, y)).toEqual(z);
- });
- });
-
- })();
Now, as per the above code, I create two test scenario. Now when I run the spec html file, the below output comes,
Unit Test of a AngularJS Controller using ngMocks
AngularJS provides an optional module called ngMock, which provides useful tools for unit testing. Go to http://angularjs.org, click Download, select the version you require and click the download button. Now, add this file into your project directive script folder and also take the file reference into the index.html file. We can also download this file using npm with command line as per below command npm install angular-mocks.
Understanding the Mock Objects
Mocking is the process of creating objects that replace the key components in an application to allow effective unit testing. Imagine that you need to test a controller behavior that makes an Ajax request using the $http service. The behavior depends on a number other components and systems: the AngularJS module to which the controller belongs, the $http service, the server that processes the request, the database that contains the data that is being asked for, and so on. When the test fails, you won’t know whether the problem is caused by the controller behavior you are trying to test or because of an unrelated fault; perhaps the server has crashed or can’t connect to the database, for example. The components that the target for testing depends on are replaced with mock objects, which implement the API of the components that are required but generate fake, predictable results. You alter the behavior of the mock objects to create different scenarios in which to test your code, which makes it easy to arrange a wide range of tests without having to endlessly reconfigure test servers, databases, networks, and so on.
The Test Objects and APIs
In this section I am going to list the mock objects and some additional features that AngularJS provides to make testing easier. I’ll then use these in the rest of the article so that I can explain how they are used to create focused and effective unit tests. The ngMocks module contains a set of mock objects that are used to replace AngularJS components, as below.
Name | Descriptions |
angular.mock | Used to create mock modules and resolve dependencies. |
$exceptionHandler | A mock implementation of the $exceptionHandler service that rethrows the exceptions it receives. |
$interval | A mock implementation of the $interval service that allows time to be moved forward to trigger scheduled functions on demand. |
$log | A mock implementation of the $log service that exposes the messages it receives through a set of properties, one for each of the methods defined by the real service. |
$timeout | A mock implementation of the $timeout service that allows the timer to be expired programmatically so that the associated function executed on demand. |
The angular.mock object provides methods that load modules and allows dependencies to be resolved in unit tests. I have described the available methods as below.
Name | Descriptions |
module(name) | Loads the specified module. See the “Arranging the Test” section. |
inject(fn) | Resolves dependencies and injects them into a function |
dump(object) | Serializes an AngularJS object (such as a service object). |
$rootScope.new() | Creates a new scope |
$controller(name) | Creates an instance of the specified controller |
$filter(name) | Creates an instance of the specified filter |
Now, we add another js file named calculateController.js file and write down the controller file with four different method which takes two number as input from html page and perform add, subtract, multiply and divide process and return the respective results.
CalculateController.js
- testApp.controller('calculateController', function ($scope) {
- $scope.FirstNum = 0;
- $scope.SecondNum = 0;
-
- $scope.add = function () {
- return $scope.FirstNum + $scope.SecondNum;
- }
-
- });
Index.html
- <!doctype html>
- <html>
- <head>
- <title>Jasmine Spec Runner</title>
- <link href="../test_resource/jasmine.css" rel="stylesheet" />
- </head>
- <body>
- <script src="../test_resource/jasmine.js"></script>
- <script src="../test_resource/jasmine-html.js"></script>
- <script src="../test_resource/boot.js"></script>
-
- <script src="../../../RefScript/angular.min.js"></script>
- <script src="../test_resource/angular-mocks.js"></script>
- <script src="../CodeJs/testApp.js"></script>
- <script src="../CodeJs/calculateController.js"></script>
-
- <script src="spec/test.js"></script>
- </body>
- </html>
test.js
- (function () {
- 'use strict';
-
- describe('Angular JS Controller Test', function () {
- var $mockScope = {};
- var $controller;
-
- beforeEach(angular.mock.module("TestApp"));
-
- beforeEach(angular.mock.inject(function ($controller, $rootScope) {
- $mockScope = $rootScope.$new();
- $controller = $controller("calculateController", {
- $scope: $mockScope
- });
- }));
-
-
- it('add method', function () {
- $mockScope.FirstNum = 10;
- $mockScope.SecondNum = 15;
- expect($mockScope.add()).toEqual(25);
- });
- });
-
- })();
I need two things to perform this test: an instance of the controller and a scope to pass to its factory function. To reach that point, I have to do some preparation. The first step is to load the module that contains the controller, which I do using beforeEach function of jasmine. As you have seen throughout this article series, dependency injection is an important part of how AngularJS works, and that means unit tests need to be able to resolve dependencies in order to function. The angular.mock.inject method will resolve the dependencies on the function it is passed, and this provides access to the services required for the test. The function I passed to the inject method declares dependencies on the $controller and $rootScope services. In general, the inject method is used to arrange the unit test, and the function that it is passed sets up test variables that will later be used in Jasmine it calls. My goal in the function shown earlier is to create a new scope and pass it to an instance of the controller in the example application so that it can define its behavior and data.
The $rootScope service defines a $new method that creates a new scope, and the $controller service is a function used to instantiate controller objects. The arguments to the $controller service function are the name of the controller and an object whose properties will be used to resolve the dependencies declared by the controller’s factory function. My simple controller requires only a scope for its factory function, but more complex controllers will require other services (which you can obtain through the inject method). By the time that the function passed to the inject method has completed, the controller will have been instantiated, and its factory function will have operated on the scope I created. I assigned the scope object to a variable called $mockScope, which I can then use in the act and assert phases of the test.
Now within the Jasmine it function, I defined the scope value and then call the add() using expect function and then assert the return result with the expected value. Now just open the index.html file in browser and see the output.
In this article, I discuss how to perform unit tests using Jasmine for simple JavaScript functions and a simple AngularJS controller file. In the next article, I will discuss about how to perform the unit test with ajax requests including directive and service tests.