Unit Testing with AngularJS: Working with Karma and Jasmine

To make sure that the test configuration is working, I am going to create a simple unit test that doesn’t use AngularJS at all. This will let me ensure that Karma and Jasmine are up and running as expected before I introduce the testing facilities that the ngMocks module provides.

You can put your test files anywhere you like in a project as long as you specify the location when you create the Karma configuration file. My preference is to keep the tests in a folder called, obviously enough, tests so they don’t clutter up my view of the application files. This is the approach that I am going to take in this chapter, but there are no hard-and-fast rules, and you should follow whatever approach makes most sense for your own workflow.

Jasmine tests are defined using JavaScript, and to get started, I created the angularjs/tests folder and added to it a file called firstTest.js, the contents of which are shown in Listing 25-3.

Listing 25-3. The Contents of the firstTest.js File

describe(“First Test”, function () {

// Arrange (set up a scenario)

var counter;

beforeEach(function () {

counter = 0;

});

it(“increments value”, function () {

// Act (attempt the operation)

counter++;

// Assert (verify the result)

expect(counter).toEqual(1);

})

it(“decrements value”, function () {

// Act (attempt the operation)

counter–;

// Assert (verify the result)

expect(counter).toEqual(0);

})

});

Tip For the eagle-eyed reader, this unit test contains a deliberate problem so that I can demonstrate how Karma runs Jasmine tests. I fix the problem in Listing 25-4.

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 five Jasmine functions in the example, which I have described in Table 25-3.

Don’t worry if you are new to unit testing and these function names don’t make sense; you’ll quickly get the hang of things as you see more examples. 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 in Table 25-4.

Tip You can use not to test for the inverse of one of these methods. For example, expect(x).not.toEqual(val) asserts that x doesn’t have the same value a val.

1. Running the Tests

The configuration I used to set up Karma earlier in the chapter means that it will monitor the JavaScript files in the angularjs and angularjs/tests folders and run all of the Jasmine tests when there is a change. To start Karma, enter the following command at the command line from within the angularjs folder:

karma start karma.config.js

Karma will load its configuration file and start an instance of Chrome so that it has a browser to work with. It will also run all of the Jasmine tests it finds, producing output like this:

C:\angularjs>karma start karma.config.js

INFO [karma]: Karma vO.10.6 server started at http://localhost:9876/

INFO [launcher]: Starting browser Chrome

INFO [Chrome 31.0.1650 (Windows)]: Connected on socket G7kAD8HkusX5AF4ZDQtb

Chrome 31.0.1650 (Windows) First Test decrements value FAILED

Expected -1 to equal 0.

Error: Expected -1 to equal 0.

at null.<anonymous> (C:/angularjs/tests/firstTest.js:21:25)

Chrome 31.0.1650 (Windows): Executed 2 of 2 (1 FAILED) (0.141 secs / 0.015 secs)

Although a browser window is opened, the output from the tests is written to the command-line console. Karma uses color coding to make it clear that there is a problem, and you should see some red text in the console window indicating that there is a problem.

1.1. Understanding the Test Problem

There are two unit tests in the firstTest.js file. The first increments the counter, like this:

it(“increments value”, function () {

// Act (attempt the operation)

counter++;

// Assert (verify the result)

expect(counter).toEqual(1);

})

The test is called increments value (which I set as the first argument to the it function), and I use the ++ operator to increase the value of the counter variable. I then use expect and toEqual to check the value is 1. The other test decrements the counter, like this:

it(“decrements value”, function () {

// Act (attempt the operation)

counter–;

// Assert (verify the result)

expect(counter).toEqual(0);

})

The second test is called decrements value. I use the — operator to decrement counter and then use the expect and toEqual functions to check that the result is zero. The problem—and it is a common one—is that I have also used the beforeEach function to set the value of the counter variable, as follows:

beforeEach(function () {

counter = 0;

});

The function passed to beforeEach executed before each test is performed, which means that the value isn’t carried over from the first test to the second. Instead, the value is reset to zero before the second test is performed. You can see this reflected in the Karma output:

Chrome 31.0.1650 (Windows) First Test decrements value FAILED

Expected -1 to equal 0.

Error: Expected -1 to equal 0.

The name of the test, the expected value, and the actual value are all included in the output so that you can see which test or tests failed.

1.2. Fixing the Problem

To fix the problem with the test, I need to correct the assumption about the initial value of the counter variable, as shown in Listing 25-4.

Listing 25-4. Fixing the Problem in the firstTest.js File

it(“decrements value”, function () {

// Act (attempt the operation)

counter–;

// Assert (verify the result)

expect(counter).toEqual(-1);

})

When you save the changed file, Karma will automatically rerun the tests and produce the following output:

Chrome 31.0.1650 (Windows): Executed 2 of 2 SUCCESS (11.999 secs / 7.969 secs)

Now that you have seen how to write a simple Jasmine test and have Karma execute it, I will turn to the support that AngularJS provides for testing application components.

Source: Freeman Adam (2014), Pro AngularJS (Expert’s Voice in Web Development), Apress; 1st ed. edition.

Leave a Reply

Your email address will not be published. Required fields are marked *