This week we want to continue our series about Angular 2 by looking at the Unit Testing capabilities that Angular 2 provides for us. What we want to cover today is:
- Tweaking Karma to avoid using the Browser Window
- Code Coverage
- Tips to testing components
This article was written using Angular CLI version 1.0.0-beta.20-4 (Tip, if you are upgrading on windows,
rm –rf node_modules dist temp just means to delete the three directories. You can do that part manually, or install bash for Windows and run the command in bash.)
Open up the project we’ve been working on.
Drop into command line mode and run
The first thing you will notice is that this brings up the Chrome browser to run your test. I don’t know about you, but I really dislike having a browser window up. I have enough windows running on my screen as it is. This is the first thing we need to fix. To do this we are going to install PhantomJS.
npm install --save-dev phantomjs-prebuilt
Then, we need to tell karma to use PhantomJS. This is a two step process. First, we install the karma phantomjs runner
npm install --save-dev karma-phantomjs-launcher
Next, we modify the karma.conf.js file
Last, since we are not using the browser, we will need a better reporting mechanism. To do this we will install spec reporter.
npm install --save-dev karma-spec-reporter
and we replace this line in karma.conf.js
reporters: config.angularCli && config.angularCli.codeCoverage ? ['progress', 'karma-remap-istanbul'] : ['progress'],
reporters: config.angularCli && config.angularCli.codeCoverage ? ['spec', 'karma-remap-istanbul'] : ['spec'],
And we add a require line at the top of the file with the other requires
Now, when we run
We get a nice text report in our terminal windows instead of the browser popping up.
To get a code coverage report for our test use the command
ng test –cc
The code coverage files will end up in a directory named ‘coverage’ hanging off the root of your project. You can view the coverage/index.html file to see how well your files are covered.
For the purposes of this article, I’m going to assume you have some familiarity with creating Jasmine tests. If you don’t the documentation for Jasmine is pretty easy to understand.
But what I do want to cover here is how we test components.
If you open up the
app.component.spec.ts file, you’ll notice a
TestBed class that gets used quite a bit. Since your test isn’t going to test modules because they only package our other code together, you need some way of faking that out so you can test the components. To do that, you use
declarations: [ AppComponent ]
Which just sets up the declarations you need to reference the component you need to test. You can put anything in this block that you would normally put in your module definition.
TestBed method you’ll see is
TestBed.createComponent(), which you probably have guessed, creates an instance of the module so you can test it. The object it creates has a
debugElement property hanging off of it. There are two properties that hang off this object that you’ll make use of a lot.
componentInstance is the actual instance of the component that you created. Any properties and methods that your component has will be available off of
The other object that will be available is
nativeElement. This is the DOM element that the component renders to and you can use
querySelector(cssSelectorGoesHere) to select the first element matches the selector or
querySelectorAll(cssSelectorGoesHere) to retrieve an array of elements that match.
Of course, a test isn’t any good if you don’t make changes to the component and test for them. And for that we have
detectChanges(). You’ll see that being used in the third test. You’ll want to use that before you
Ready, Set, …
Now that we have some way of testing our code, we can actually begin to write so. Don’t forget to subscribe to the email I sent out so you don’t miss the next article in this series.
Code so far is located at https://github.com/DaveMBush/GettingStartedWithAngular2/tree/Step2
Other post in Angular 2
- Angular 2 – First Impressions [Compared to Angular 1] - February 25th, 2016
- Angular 2 Thoughts - October 4th, 2016
- Getting Started with Angular 2 - October 25th, 2016
- Unit Testing an Angular 2 CLI Project - November 22nd, 2016
- Adding Client Side Routing to Angular 2 - November 29th, 2016
- Angular 2 Lazy Loading - December 6th, 2016
- Reasons to use RxJS Today - December 13th, 2016
- Dissecting Angular 2 Modules - December 20th, 2016
- Awesome Angular2 Architecture Options and Opinions - December 27th, 2016
- What if Everything Was Immutable? - January 10th, 2017
- Amazing Angular2 DOM Tips, Tricks, and Warnings - January 17th, 2017
- Secrets to Styling Angular2 - January 31st, 2017
- Jedi Angular 2 Tips and Tricks - March 28th, 2017
- Unit Testing Angular(2+) with JSDOM - April 4th, 2017
- More Control with Angular Flex Layout - April 11th, 2017
- Angular(2+) Model Driven Forms Are Superior - April 18th, 2017
- Dynamically Add Components in Angular - April 25th, 2017
- Using Real World NgRX - May 9th, 2017
- Functional Reactive Angular Revealed - May 30th, 2017
- NgRX/Store Coding Sanity Epiphany - June 6th, 2017
- Real World RxJS Marble Testing Revealed - June 13th, 2017
- How to Organize an Angular Application - June 20th, 2017
- Upload an Image as a File in Angular - July 4th, 2017
- How to Implement Angular 2+ Routing - July 18th, 2017
- TypeScript Basics for Angular Developers - August 1st, 2017
- Angular Observable Secrets Revealed - August 8th, 2017
- How to Upgrade NgRX to 4.x - August 15th, 2017
- Model View Presenter, Angular, and Testing - August 29th, 2017
- This One Tweak Improved my Angular Code - September 12th, 2017
- Upgrade to Angular from... - September 26th, 2017
- Using NgRX to Cleanly Aggregate Data - October 3rd, 2017
- NgRX 4 Actions - Class vs Object Literal - October 10th, 2017
- Implementing NgRX 4 - October 24th, 2017
- What I Learned Using Angular Material - October 31st, 2017