DEV Community

loading...
Cover image for Head start with Testing in Angular with Jasmine

Head start with Testing in Angular with Jasmine

Dany Paredes
ex .NET guy, my last years building solutions with Vue, Angular, Sass, and Typescript.
・4 min read

I was working for several months with Jest and Vue, but nowadays I'm working with Angular and the testing is part of my learning process.

I will explain a little bit about Jasmine and how to write a test for typescript classes, if you found something wrong please notify by twitter @danywalls .

The testing in Angular

Angular was build to be testable, it comes with Protractor, Jasmine, and Karma to help us to build unit and E2E tests.

The Angular-cli provides scaffolding to build and run those tests and also these tools can be configured to run your test during the development or build process.

Unit tests

The unit test is to check a basic piece or units of code, that means our test only tests one responsibility of our code.

The Unit test is used for test functions, objects, and more.

The jasmine framework is the framework that angular comes to write these tests.

Jasmine functions

Jasmine framework comes with several functions, you don't need to memorize everyone but with basic, you can get started with describe, it, and expect.

describe help to group a series of tests, aka as test suite it takes 2 parameters, a string and a callback like.

describe("my group of invoice tests", () => {} );
Enter fullscreen mode Exit fullscreen mode

it function help create a specific test, close similar to describe but is used to write the test.

it("the number should be positive", () => {});
Enter fullscreen mode Exit fullscreen mode

expect function play with our test that confirms that the test work as expected, it asserts our code. the expect function expect, is where I pass in the value and the matcher function is where pass the expected value.

Some of the common matcher functions are toBe(), toBeTrurty() or toEqual().

expect(true).toBeThruthy();
Enter fullscreen mode Exit fullscreen mode

The unit test files convention is filetotest.spec.ts by default angular-cli generate app.spect.ts and you run the test with ng test command.

Write basic unit test with jasmine

Time to put my skill to test and practice what I just learned writing a small test using describe, it for the Gif class.

export class Gif {
  private _url: string;
  urlValidator = new RegExp(/^(ftp|http|https):\/\/[^ "]+$/);
  public get url(): string {
    return this._url;
  }
  public set url(v: string) {
    this._url = v;
  }
  public get isvalid(): boolean {
    return this.urlValidator.test(this.url);
  }
}
Enter fullscreen mode Exit fullscreen mode

What I can test?

  • If the public properties url and isValid has the expected value.
  • The behavior like when a not valid url the gif is invalid.
  • If can create an instance.
  • If the URL can be is assigned.

Let's go!

1- Import the Gif class and describe it to define the test group.

import { Gif } from './gif';
describe('Gif Class tests', () => {

}
Enter fullscreen mode Exit fullscreen mode

2- Using it function define the test about a valid class constructor and with expect validate it is not null.

import { Gif } from './gif';
describe('The Gif', () => {
  it('should to have a valid constructor', () => {
    const gif = new Gif();
    expect(gif).not.toBeNull();
  });
}
Enter fullscreen mode Exit fullscreen mode

Run our tests with ng test from CLI.

Chrome 85.0.4183.121 (Windows 10): Executed 1 of 1 SUCCESS (0.035 secs / 0.01 secs)
TOTAL: 1 SUCCESS
Enter fullscreen mode Exit fullscreen mode

Adding the rest tests for the public properties.

import { Gif } from './gif';
describe('The Gif', () => {
  it('should to have a valid constructor', () => {
    const gif = new Gif();
    expect(gif).not.toBeNull();
  });

  it('should set the url', () => {
    const gif = new Gif();
    gif.url = 'http://google.com';
    expect(gif.url).not.toBeNull();
  });

  it('should be invalid gif for wrong url', () => {
    const gif = new Gif();
    gif.url = 'ht';
    expect(gif.isvalid).toBe(false);
  });

  it('should be valid gif for valid url', () => {
    const gif = new Gif();
    gif.url = 'http://www.google.com';
    expect(gif.isvalid).toBe(true);
  });

  it('should asign the url string', () => {
    const gif = new Gif();
    const expectedUrl = 'http://www.google.com';
    gif.url = expectedUrl;
    expect(gif.url).toEqual(expectedUrl);
  });
});
Enter fullscreen mode Exit fullscreen mode

Then run the ng test command get the results

Alt Text

Refactor tests with beforeEach and afterEach

If we read the code, the gif instance is created for each test, it is not the best approach. Jasmine provide a solution for the setup of test with beforeEach() and afterEach() function.

The beforeEach function help run code before each test. In this case, we declare a variable as gif type and initialize it for each test.

describe('The Gif', () => {
  let gif: Gif = null;
  beforeEach(() => {
    gif = new Gif();
  });
    ... 
Enter fullscreen mode Exit fullscreen mode

The same is for afterEach, assign the gif instance to null.

afterEach(() => {
    gif = null;
  });
Enter fullscreen mode Exit fullscreen mode

The final code looks like:

import { Gif } from './gif';
describe('The Gif', () => {
  let gif: Gif = null;
  beforeEach(() => {
    gif = new Gif();
  });
  it('should to have a valid constructor', () => {
    expect(gif).not.toBeNull();
  });

  it('should set the url', () => {
    gif.url = 'http://google.com';
    expect(gif.url).not.toBeNull();
  });

  it('should be invalid for wrong url', () => {
    gif.url = 'ht';
    expect(gif.isvalid).toBe(false);
  });

  it('should be valid for valid url', () => {
    gif.url = 'http://www.google.com';
    expect(gif.isvalid).toBe(true);
  });

  it('should asign the url string', () => {
    const expectedUrl = 'http://www.google.com';
    gif.url = expectedUrl;
    expect(gif.url).toEqual(expectedUrl);
  });
  afterEach(() => {
    gif = null;
  });
});

Enter fullscreen mode Exit fullscreen mode

Run the new tests with the ng test command from your terminal.

ng test
Enter fullscreen mode Exit fullscreen mode

Alt Text

Done!

You should feel confident for write your first tests using Jasmine for your Angular Apps.

Discussion (5)

Collapse
stealthmusic profile image
Jan Wedel

We’ve had a lot of issues with Karma and Protractor in a very large application so we eventually migrated to Cypress and Jest which is interesting because that’s where you came from. What are your thoughts about Karma vs Jest? I would exclude Jasmina because you can use the same test structure also with Jest.

Collapse
danywalls profile image
Dany Paredes Author

I'm using karma because comes by default with Angular, but these are 3 missing points from Jest
1- Jest is faster (of course don't need a browser)
2- Jest configuration is easy.
3-Debug and run with VSCode.

I will finish my process with Karma, maybe I will try looking how to migrate to move my tests to Jest :D

Collapse
avarissou profile image
aziz varissou

thanks, very useful

Collapse
danywalls profile image
Dany Paredes Author

Soon head start with Component Testing in Angular ;)

Collapse
danywalls profile image
Dany Paredes Author

I try to speed up a little bit my jasmine test using ChromeHeadLess
dev.to/danywalls/speed-up-karma-an...