Bob at Genuitec Virtual evangelist at large. The face of Genuitec often appearing in graphics. Pen-name for our more shy writers of content.

Testing is one of the most important aspects of the modern application development process. Today, high quality, robust applications are the norm; nobody appreciates a buggy application. This article will walk you through testing your Angular application using capabilities that are already part of your Angular project.

Creating a New Angular Project

We’re going to be using Angular IDE through this tutorial, though you can use Webclipse or MyEclipse too, following exactly the same steps. Before beginning, do ensure you are in the Angular Perspective (Window > Perspective > Open Perspective > Other > Angular) for an optimum workspace layout and development experience.

In the new Angular project wizard (File > New > Angular Project), type Angular1 as the project name – you may change the Node.js, npm and Angular CLI versions if desired.

Finally, click Finish to complete the creation of a new Angular project. In the Terminal+ view, you can see several commands being executed by Angular CLI. After the installation of all the modules, we are now ready to continue with development.

Did you know that CodeLive makes it really easy to explore Angular applications? Hover over a component on the page to view the component name, and click the component to view the dashboard list, filtered for the selected component. Easily jump to the corresponding TypeScript, HTML, or CSS file. Watch this video for a quick demo.

Testing Modules in Your Angular Project

Jasmine

Jasmine is a JavaScript testing framework that supports a software development practice called Behavior Driven Development (BDD) – a specific flavor of Test Driven Development (TDD). It does not require a DOM, and has a clean, obvious syntax so that you can easily write tests.

The general syntax of a Jasmine test suite is given as follows:

1 2 3 4 5 describe ( " dunebook Jasmine example" , function ( ) { it ( "This is a spec that defines test" , function ( ) { expect ( actual ) . toBe ( true ) ; } ) ; } ) ;

Let’s understand the code snippet above:

describe defines a test suite, it takes a string and function as parameters.

defines a test suite, it takes a string and function as parameters. it , like describe , also takes a string and a function, and defines a test/spec.

, like , also takes a string and a function, and defines a test/spec. expect takes a value, called the actual, which is compared via one of several matchers ( toBe in this case) to an expected value.

Karma

Karma, on the other hand, is not a framework to write tests, but it is a test runner. Karma gives us the ability to run automated tests in several different browsers, and makes it easy to integrate with a continuous integration server. It requires additional frameworks, like Jasmine.

Note: Your Angular project already contains both Karma and Jasmine packages by default, no additional installations are necessary.

Testing an Angular Component

We’re going to modify the generated root component so we can create a simple test.

Modifying our Angular Root Component

Replace the source of src/app/app.component.ts with:

1 2 3 4 5 6 7 8 9 10 import { Component } from '@angular/core' ; @ Component ( { selector : 'app-root' , templateUrl : './app.component.html' , styleUrls : [ './app.component.css' ] } ) export class AppComponent { title = 'angular 4 testing' ; }

Replace the source of app.component.html with:

1 2 3 <div style = "text-align: center" > <h1> Welcome to {{title}}!! </h1> </div>

The app.component.spec.ts file is responsible for testing, we’re going to replace its source with:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 import { TestBed , async } from '@angular/core/testing' ; import { AppComponent } from './app.component' ; describe ( 'AppComponent' , ( ) = > { beforeEach ( async ( ( ) = > { TestBed . configureTestingModule ( { declarations : [ AppComponent ] , } ) . compileComponents ( ) ; } ) ) ; it ( 'it should work well' , async ( ( ) = > { const fixture = TestBed . createComponent ( AppComponent ) ; const app = fixture . debugElement . componentInstance ; expect ( app ) . toBeTruthy ( ) ; } ) ) ; it ( ` should have as title 'angular 4 testing' ` , async ( ( ) = > { const fixture = TestBed . createComponent ( AppComponent ) ; const app = fixture . debugElement . componentInstance ; expect ( app . title ) . toEqual ( 'angular 4 testing' ) ; } ) ) ; it ( 'should render title in a h1 tag' , async ( ( ) = > { const fixture = TestBed . createComponent ( AppComponent ) ; fixture . detectChanges ( ) ; const compiled = fixture . debugElement . nativeElement ; expect ( compiled . querySelector ( 'h1' ) . textContent ) . toContain ( 'Welcome to angular 4 testing' ) ; } ) ) ; } ) ;

Let’s go over the above code snippet in detail:

We have imported the required modules namely TestBed and async from angular/core/testing . In the first test script, we wrote a simple expect statement for the component, tobeTruthy. In the second test script, we created an instance of the component via TestBed.createComponent :

• We created an instance of the root component via TestBed.createComponent .

• Using debugElement , we created the instance of the created component, app .

• Using app , we are able to get the title of the component, and use the toEqual assertion to check whether the title is equal to “angular 4 testing”. In the last test script we use debugElement#nativeElement method and target <h1> . Here we are checking if <h1> contains, “Welcome to angular 4 testing”. The difference between the second and third test scripts is that in third script we are waiting for changes to be detected by using the detectChanges method.

Testing an Angular Service

We’re going to go ahead now and test an Angular Service as well. To create a new Angular Service in Angular IDE, we use File > New > Service. Type app into the Element Name field.





app.service.spec.ts

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 import { TestBed , inject } from '@angular/core/testing' ; import { AppService } from './app.service' ; describe ( 'AppService' , ( ) = > { beforeEach ( ( ) = > { TestBed . configureTestingModule ( { providers : [ AppService ] } ) ; } ) ; it ( 'App service is Running Fine' , inject ( [ AppService ] , ( service : AppService ) = > { expect ( service ) . toBeTruthy ( ) ; } ) ) ; } ) ;

The assertion in the code above is true if service , an instance of AppService (obtained via Dependency Injection), is not null.

Running the Tests

Before we run the tests, you might want to run the project itself, to see the output we’re expecting, in the browser.

There is a server view in Angular IDE, as shown in the image below (Window > Show View > Servers). Right click on your project (here Angular1 ) and select Start Server . Angular IDE serves the application on localhost port 4200 by default. So open http://localhost:4200 in your browser to see the running app.

You should see a screen like the one below at http://localhost:4200.

ng test

This command opens a browser window with the test results – as you can see in the above screenshot, all specified tests have been executed and have passed.

Note: Press Ctrl + C in the Terminal+ view to end the test run, else it will reopen the test result browser each time you close it.

Creating an Advanced Test

Our tests so far were rather basic, let’s do something a bit more advanced, by replacing our service code and service test.

Replace the code in src/app/app.service.ts with:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 import { Injectable } from '@angular/core' ; @ Injectable ( ) export class AppService { getTopicCount ( ) { const Topics = [ { name : 'laravel' } , { name : 'angular' } , { name : 'java' } , { name : 'python' } ] ; return Object . keys ( Topics ) . length ; } }

We’ve defined the getTopicCount method to return the number of elements in the Topics array.

Replace the testing code in app.service.spec.ts with:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 import { TestBed , inject } from '@angular/core/testing' ; import { AppService } from './app.service' ; describe ( 'AppService' , ( ) = > { beforeEach ( ( ) = > { TestBed . configureTestingModule ( { providers : [ AppService ] } ) ; } ) ; it ( ' Angular Service should return 3 values' , inject ( [ AppService ] , ( service : AppService ) = > { let countTopic = service . getTopicCount ; expect ( countTopic ) . toBe ( 3 ) ; } ) ) ; } ) ;

Like the last service test example, we obtain the service instance using dependency injection, then call the getTopicCount method to check whether the count returned is 3. The beforeEach function is called before each test in the suite, usually used to set up tests; in this case it ensures we can get the service instance we are interested in.

Again, in Terminal+, execute ng test to execute the tests.

After running the test, you will see that our latest test has failed, as our test expected a count of 3, while the actual count was 4.

In Closing

If you’re interested in learning more about testing, you may also want to take a look at Mocha, which is an alternative to Jasmine. Libraries like Chai and Sinon, may also come in handy, and can be used within your tests in either framework.

While we used Angular IDE in our tutorial today, if you already have an Eclipse install you are happy with, you can get the same functionality by installing Webclipse. Finally, if you’re looking for a full-stack experience with Java EE at the back end, try MyEclipse.

Whatever framework and tool you use, don’t forget to test, and develop tests alongside regular functionality – it’s a strategy that will pay huge dividends in the long run.