Get started testing Angular 5 with Jasmine and Karma. This video covers basic testing component TDD concepts as well as 3rd party services like Firebase. https://angularfirebase.com/lessons/angular-testing-guide-including-firebase/

Jasmine: https://jasmine.github.io/
Testing Docs: https://angular.io/guide/testing
Great Article: https://medium.com/javascript-scene/tdd-the-rite-way-53c9b46f45e3
2024-02-04T07:52:45.376Z
nova-2
2-general-nova
2024-01-09.29447
30089e05-99d1-4376-b32e-c263170674af
1ebfe187-ad14-4db2-aa76-4dc687d511c4
aaa66f8948f5197a01a812fd9b226f4f75cc9b9f87f7ba43d7af31b6ea9f2758
67875a7f-c9c4-48a0-aa55-5bdb8a91c34a
deprecated
Test driven development is the single most powerful tool you have for preventing bugs within your application.
That's not just my opinion, but it's a scientifically proven fact.
In exchange for effort and productivity, you get better quality software that is more maintainable long term.
Lucky for you, Angular comes built in with Jasmine and Karma, so testing is really easy to get started with.
In this video, I'll give you a tour of Angular's testing tools and show you how to deal with third party dependencies like Firebase.
F If you're new to the channel, make sure to subscribe, and you can always get the full source code on angularfirebase.com.
The first thing I'm going to do is generate a brand new Angular Fiber5 app, and then I'll show you what all the different testing files do.
The Angular CLI generates all of the boilerplate code automatically, so so we'll start by looking at the Karma config file.
Karma works by setting up a web server that will run all of your tests automatically every time a file changes.
You have some configuration options here if you want to customize that experience.
You also have a protractor config file, which is specifically for end to end tests.
Fact.
End to end testing uses the browser to simulate how the end user sees your app, so it's completely decoupled from your main app code.
That's why we have this e to e directory in the root of the project, and I'll show you how to use it in a future video.
Now moving into the source directory, we have a test TS file.
It's required by Karma to load all your spec files.
You shouldn't really have to change anything in here.
Now let's take a look at our first real test, which is the App component spec TS file.
This just looks like a big jumble of code, so let's break the test down into its fundamental parts.
The first part of any test is to describe the test suite.
In Jasmine, you do this by using the describe keyword followed by whatever you're testing.
The purple text represents Jasmine.
The green represents what we're going to write.
Fact.
We write all the tests inside this describe block, each one starting with it.
So we're going to say it should be awesome.
Then you'll write an expectation that verifies whether this is true or false.
So with Jasmine, we could do something like expect component to be awesome.
The end result is that you've described the behavior of your code in a way that can be easily read by a non programmer.
Describing and validating your code in this way is the reason that testing is so effective at reducing bugs.
Now we need something to test, so I'm going to start by generating this alert button component.
It's just a simple button that will toggle the visibility of this alert message whenever it's clicked.
Fact.
We'll start by testing its static values, but eventually, we'll use AngularFire 2 to populate its warning message.
If if we look at the component typescript, I just have a couple of properties hard coded in here, and then I have a toggle method that will toggle the value of the hide content property.
Fact.
Then the template HTML just shows these properties and adds a button that will toggle the visibility of that message.
The message is hidden by default, and that's something we're gonna test here in the 5 steps.
So now let's set up our alert button spec from scratch.
The first thing we're going to do is import Angular's testing utilities And then we're going to describe our test suite, which is the Angular button component.
At this point, we're going to declare a variable for the fixture, and a fixture is just the test environment for this component.
So it provides access to the component itself as well as its debug element, which is its rendered HTML.
Fact.
Now before each spec, we need to set up a test bed, which is just an NG module specific for this testing environment.
The most simple example is just an isolated test of the component itself and that's where we're going to start, but this will get increasingly more complex.
If you wanna compile the components HTML and CSS, then you'll call this compile components method after the test bed.
After the test bed's been compiled, we can then set up a few variables here that we'll actually use for testing.
We can test the component directly or we can test its rendered HTML via the debug element.
And lastly, we'll run Angular change detection before each of these tests, but you could test things before change detection as well.
Now we're ready to write the first spec.
The first thing we'll test is whether or not the component is created successfully.
So we can say it should create and then we'll expect component to be truthy.
Just a quick side note, truthy means that something evaluates to true in a boolean context.
Fix.
It doesn't mean what you're testing is actually the primitive true value.
This is one of the many Jasmine matchers, and I recommend going to the docs to get acquainted with all of them.
Now that we have our spec, we can just run ng test, and that'll bring up a browser window saying whether or not it passed or failed.
Now I'm just gonna leave Karma running so we can see how it updates every time we write a new spec.
The second spec is going to see whether or not the content message has a substring of warn.
In this case, the content was just hard coded as a property on the component, so we can say component content to contain the string of warn.
Fact.
The to contain matcher will check for a substring, or if it was an array, it would check for an element in that array.
Now if we save this file, you can see the Karma runner on the left will update with the spec, and it will be passing as well.
So the actual message content is you will be warned.
So let's see what happens if we use a Jasmine Matcher that looks for an exact match.
Fact.
This time, we'll get a failing test, and it's also going to tell us exactly why it failed.
It expected the string of you have been warned to be warned, which would be false.
You can also rate specs based on logical numeric values.
So let's say we have a severity level on the alert and we wanna see if it is greater than 2.
In In this case, it's actually 423.
So if we say expect component severity to be greater than 2, that should be a passing test.
So far, we've only tested properties on the component itself, but now let's see if it actually rendered properly in the DOM.
So let's say it should have an h one tag of alert button.
To do that, we use the debug element and it has a DSL that allows us to query elements in the DOM.
So we would say query by the CSS of h one, Then we can get the native HTML element.
At that point, we just have the string that's inside the h one tag, and then we can validate that it is the alert written text.
So now let's move on to a spec that will tell us whether or not a function is doing what it's supposed to do.
We wrote a toggle method earlier that toggles a Boolean variable.
So we'll say it should toggle the message Boolean, and first, we'll expect the component hide content to be truthy because it's hidden by default.
Fact.
Then we can execute that toggle button method, then we'll run another expectation that this time the component hide content boolean is falsy.
That one passes as well, so we know that our method is performing what it's supposed to perform.
But what if that change happens asynchronously as many things do in Angular?
Fact.
Back in the component, I'm going to define a method called toggle async, which will run the toggle method after an RxJS timer of 500 milliseconds runs out.
Fact.
The spec is going to be it should toggle the message Boolean asynchronously, then we're going to wrap this in the fake async helper from Angular.
This creates a fake Angular zone that we can use to test asynchronous activity.
The test is exactly the same as the last one, but calls the toggle async method.
Fact.
As you can see here, it fails because Angular doesn't wait for the 500 milliseconds to run out before testing that property.
We also have a tick utility that we can use here in the fake async block.
And so if we set that to 499 milliseconds, you can see here that we still get a failing test.
Fact.
The timer we set is 500 milliseconds, so if we add just one more millisecond to it, then the test will pass.
That That gives you a few basic examples of Angular component testing, but now let's add a service to the mix using AngularFire 2.
What we're going to do is create a service that returns an observable from the Firebase real time database, and that's going to replace the content that we had hard coded in the component before.
If you're not familiar with AngularFire 2, make sure to follow the setup instructions on the main documentation.
You also need to have a Firebase account.
And inside the real time database, I have an alerts node with a test alert that says, you have been warned.
Then I am going to generate a service with the CLI, And you can test your service directly, but for this video, we're just gonna focus on the component.
The service itself is very simple.
We just add AngularFire database to the constructor, And then we'll set up one method in here called get content, which will retrieve that message from the database as an observable.
When running your tests, You don't wanna actually use live data from the real back end.
You should only simulate how that back end data would be returned by using what's called a stub.
Fact.
A stub is simply a method that returns some data in a way that's predictable and reproducible.
So what I'm doing here is setting up a variable called Service stub.
Fact.
It's going to be an object that has a function in it that returns the observable in the same form that we'd expect back from Firebase.
Fact.
So the Get Content property is a function that returns an observable of the message, you have been warned.
This gives us mock data that we can use to interact with the service without actually having to make a real request to Firebase.
Then we can use this stub as a service by adding it to our test bed in the providers array.
But instead of providing a live service, we do an object that has provide with the message service and then use value with our service stub.
This tells the test environment to use the stub instead of the actual live data.
At this point, all we have to do is write our spec, and it should return this observable like we would expect.
This time, we'll say it should have message content defined from an observable.
And then what we'll do is subscribe to that observable and put our expectations inside the scribe block.
We expect the content to be defined, and to be you have been warned.
This is the easiest way to test mock data from a service, but it is limited in certain respects.
For example, we can't tell how many times this method has been called, which might be important if you have a method that is not idempotent.
To address this, I'm going to stub our service using a different method called a Spy.
This time, we're going to actually use the live service, so So we're going to need to set up our test bed with AngularFire 2.
Then I'll set another variable for our service and another one for the Spy.
From there, I'm going to add AngularFire 2 to the import section of the test bed.
And then in the provider section, I'll take out the stub and add the live service to it.
Fact.
Then we can get rid of our previous service stub, and then we'll set up the Spy here, which comes from Jasmine.
We can call Spy on and then pass it fact.
The main service class as well as the method that we wanna monitor.
So in this case, it's going to be our Get Content method.
We still don't want to use any live data from Firebase, so what we do is tell our Spy to return a value of an observable of the message.
What this is going to do is allow us to see whenever this method has been called and with what arguments it was called with, and it's never going to actually make a live request so it just stubs the return value.
And to get the service class, we call debug element injector get with the message service.
Fact.
So our SPY is ready to go.
Now we can just jump down and write our next spec.
This time, I wanna make sure that the method is only called once and I wanna make sure that the view is updated with the corresponding observable data.
So we can make sure our service method was called by calling expect spy to have been called.
Then we can see how many times it was called by calling spies calls all, which is an array.
And then we can test the length of that array, and it should be 1.
So we'll say 2 equal 1.
Then we're also unwrapping an Observable in the HTML, so I wanna make sure that this method results in an observable that gets rendered in the HTML itself.
So we'll use query on the debug element to get the message body.
Then we can look at the native element inner text, and that should be the message you have been warned.
So we can just call to contain warn to verify that.
Fact.
Then we can go ahead and save it and it's going to run our spec and it passes as expected.
The spy can do a whole bunch of other stuff too, like see where the method was called and with which arguments.
So check out the Jasmine docs for more information on that.
That's it for Angular component testing basics.
If this video helped you, please like and subscribe.
And if you want to learn more advanced concepts, consider becoming a pro subscriber at angularfirebase.com.
You'll get a whole bunch of exclusive content, 1 on 1 project support via Slack and a free copy of my book.
Thanks for watching, and I'll see you soon.

Speaker 0: Test driven development is the single most powerful tool you have for preventing bugs within your application. That's not just my opinion, but it's a scientifically proven fact. In exchange for effort and productivity, you get better quality software that is more maintainable long term. Lucky for you, Angular comes built in with Jasmine and Karma, so testing is really easy to get started with. In this video, I'll give you a tour of Angular's testing tools and show you how to deal with third party dependencies like Firebase.

F If you're new to the channel, make sure to subscribe, and you can always get the full source code on angularfirebase.com. The first thing I'm going to do is generate a brand new Angular Fiber5 app, and then I'll show you what all the different testing files do. The Angular CLI generates all of the boilerplate code automatically, so so we'll start by looking at the Karma config file. Karma works by setting up a web server that will run all of your tests automatically every time a file changes. You have some configuration options here if you want to customize that experience.

You also have a protractor config file, which is specifically for end to end tests. Fact. End to end testing uses the browser to simulate how the end user sees your app, so it's completely decoupled from your main app code. That's why we have this e to e directory in the root of the project, and I'll show you how to use it in a future video. Now moving into the source directory, we have a test TS file.

It's required by Karma to load all your spec files. You shouldn't really have to change anything in here. Now let's take a look at our first real test, which is the App component spec TS file. This just looks like a big jumble of code, so let's break the test down into its fundamental parts. The first part of any test is to describe the test suite.

In Jasmine, you do this by using the describe keyword followed by whatever you're testing. The purple text represents Jasmine. The green represents what we're going to write. Fact. We write all the tests inside this describe block, each one starting with it.

So we're going to say it should be awesome. Then you'll write an expectation that verifies whether this is true or false. So with Jasmine, we could do something like expect component to be awesome. The end result is that you've described the behavior of your code in a way that can be easily read by a non programmer. Describing and validating your code in this way is the reason that testing is so effective at reducing bugs.

Now we need something to test, so I'm going to start by generating this alert button component. It's just a simple button that will toggle the visibility of this alert message whenever it's clicked. Fact. We'll start by testing its static values, but eventually, we'll use AngularFire 2 to populate its warning message. If if we look at the component typescript, I just have a couple of properties hard coded in here, and then I have a toggle method that will toggle the value of the hide content property.

Fact. Then the template HTML just shows these properties and adds a button that will toggle the visibility of that message. The message is hidden by default, and that's something we're gonna test here in the 5 steps. So now let's set up our alert button spec from scratch. The first thing we're going to do is import Angular's testing utilities And then we're going to describe our test suite, which is the Angular button component.

At this point, we're going to declare a variable for the fixture, and a fixture is just the test environment for this component. So it provides access to the component itself as well as its debug element, which is its rendered HTML. Fact. Now before each spec, we need to set up a test bed, which is just an NG module specific for this testing environment. The most simple example is just an isolated test of the component itself and that's where we're going to start, but this will get increasingly more complex.

If you wanna compile the components HTML and CSS, then you'll call this compile components method after the test bed. After the test bed's been compiled, we can then set up a few variables here that we'll actually use for testing. We can test the component directly or we can test its rendered HTML via the debug element. And lastly, we'll run Angular change detection before each of these tests, but you could test things before change detection as well. Now we're ready to write the first spec.

The first thing we'll test is whether or not the component is created successfully. So we can say it should create and then we'll expect component to be truthy. Just a quick side note, truthy means that something evaluates to true in a boolean context. Fix. It doesn't mean what you're testing is actually the primitive true value.

This is one of the many Jasmine matchers, and I recommend going to the docs to get acquainted with all of them. Now that we have our spec, we can just run ng test, and that'll bring up a browser window saying whether or not it passed or failed. Now I'm just gonna leave Karma running so we can see how it updates every time we write a new spec. The second spec is going to see whether or not the content message has a substring of warn. In this case, the content was just hard coded as a property on the component, so we can say component content to contain the string of warn.

Fact. The to contain matcher will check for a substring, or if it was an array, it would check for an element in that array. Now if we save this file, you can see the Karma runner on the left will update with the spec, and it will be passing as well. So the actual message content is you will be warned. So let's see what happens if we use a Jasmine Matcher that looks for an exact match.

Fact. This time, we'll get a failing test, and it's also going to tell us exactly why it failed. It expected the string of you have been warned to be warned, which would be false. You can also rate specs based on logical numeric values. So let's say we have a severity level on the alert and we wanna see if it is greater than 2.

In In this case, it's actually 423. So if we say expect component severity to be greater than 2, that should be a passing test. So far, we've only tested properties on the component itself, but now let's see if it actually rendered properly in the DOM. So let's say it should have an h one tag of alert button. To do that, we use the debug element and it has a DSL that allows us to query elements in the DOM.

So we would say query by the CSS of h one, Then we can get the native HTML element. At that point, we just have the string that's inside the h one tag, and then we can validate that it is the alert written text. So now let's move on to a spec that will tell us whether or not a function is doing what it's supposed to do. We wrote a toggle method earlier that toggles a Boolean variable. So we'll say it should toggle the message Boolean, and first, we'll expect the component hide content to be truthy because it's hidden by default.

Fact. Then we can execute that toggle button method, then we'll run another expectation that this time the component hide content boolean is falsy. That one passes as well, so we know that our method is performing what it's supposed to perform. But what if that change happens asynchronously as many things do in Angular? Fact.

Back in the component, I'm going to define a method called toggle async, which will run the toggle method after an RxJS timer of 500 milliseconds runs out. Fact. The spec is going to be it should toggle the message Boolean asynchronously, then we're going to wrap this in the fake async helper from Angular. This creates a fake Angular zone that we can use to test asynchronous activity. The test is exactly the same as the last one, but calls the toggle async method.

Fact. As you can see here, it fails because Angular doesn't wait for the 500 milliseconds to run out before testing that property. We also have a tick utility that we can use here in the fake async block. And so if we set that to 499 milliseconds, you can see here that we still get a failing test. Fact.

The timer we set is 500 milliseconds, so if we add just one more millisecond to it, then the test will pass. That That gives you a few basic examples of Angular component testing, but now let's add a service to the mix using AngularFire 2. What we're going to do is create a service that returns an observable from the Firebase real time database, and that's going to replace the content that we had hard coded in the component before. If you're not familiar with AngularFire 2, make sure to follow the setup instructions on the main documentation. You also need to have a Firebase account.

And inside the real time database, I have an alerts node with a test alert that says, you have been warned. Then I am going to generate a service with the CLI, And you can test your service directly, but for this video, we're just gonna focus on the component. The service itself is very simple. We just add AngularFire database to the constructor, And then we'll set up one method in here called get content, which will retrieve that message from the database as an observable. When running your tests, You don't wanna actually use live data from the real back end.

You should only simulate how that back end data would be returned by using what's called a stub. Fact. A stub is simply a method that returns some data in a way that's predictable and reproducible. So what I'm doing here is setting up a variable called Service stub. Fact.

It's going to be an object that has a function in it that returns the observable in the same form that we'd expect back from Firebase. Fact. So the Get Content property is a function that returns an observable of the message, you have been warned. This gives us mock data that we can use to interact with the service without actually having to make a real request to Firebase. Then we can use this stub as a service by adding it to our test bed in the providers array.

But instead of providing a live service, we do an object that has provide with the message service and then use value with our service stub. This tells the test environment to use the stub instead of the actual live data. At this point, all we have to do is write our spec, and it should return this observable like we would expect. This time, we'll say it should have message content defined from an observable. And then what we'll do is subscribe to that observable and put our expectations inside the scribe block.

We expect the content to be defined, and to be you have been warned. This is the easiest way to test mock data from a service, but it is limited in certain respects. For example, we can't tell how many times this method has been called, which might be important if you have a method that is not idempotent. To address this, I'm going to stub our service using a different method called a Spy. This time, we're going to actually use the live service, so So we're going to need to set up our test bed with AngularFire 2.

Then I'll set another variable for our service and another one for the Spy. From there, I'm going to add AngularFire 2 to the import section of the test bed. And then in the provider section, I'll take out the stub and add the live service to it. Fact. Then we can get rid of our previous service stub, and then we'll set up the Spy here, which comes from Jasmine.

We can call Spy on and then pass it fact. The main service class as well as the method that we wanna monitor. So in this case, it's going to be our Get Content method. We still don't want to use any live data from Firebase, so what we do is tell our Spy to return a value of an observable of the message. What this is going to do is allow us to see whenever this method has been called and with what arguments it was called with, and it's never going to actually make a live request so it just stubs the return value.

And to get the service class, we call debug element injector get with the message service. Fact. So our SPY is ready to go. Now we can just jump down and write our next spec. This time, I wanna make sure that the method is only called once and I wanna make sure that the view is updated with the corresponding observable data.

So we can make sure our service method was called by calling expect spy to have been called. Then we can see how many times it was called by calling spies calls all, which is an array. And then we can test the length of that array, and it should be 1. So we'll say 2 equal 1. Then we're also unwrapping an Observable in the HTML, so I wanna make sure that this method results in an observable that gets rendered in the HTML itself.

So we'll use query on the debug element to get the message body. Then we can look at the native element inner text, and that should be the message you have been warned. So we can just call to contain warn to verify that. Fact. Then we can go ahead and save it and it's going to run our spec and it passes as expected.

The spy can do a whole bunch of other stuff too, like see where the method was called and with which arguments. So check out the Jasmine docs for more information on that. That's it for Angular component testing basics. If this video helped you, please like and subscribe. And if you want to learn more advanced concepts, consider becoming a pro subscriber at angularfirebase.com.

You'll get a whole bunch of exclusive content, 1 on 1 project support via Slack and a free copy of my book. Thanks for watching, and I'll see you soon.
Test driven development is the single most powerful tool you have for preventing bugs within your application. That's not just my opinion, but it's a scientifically proven fact. In exchange for effort and productivity, you get better quality software that is more maintainable long term. Lucky for you, Angular comes built in with Jasmine and Karma, so testing is really easy to get started with. In this video, I'll give you a tour of Angular's testing tools and show you how to deal with third party dependencies like Firebase. F If you're new to the channel, make sure to subscribe, and you can always get the full source code on angularfirebase.com. The first thing I'm going to do is generate a brand new Angular Fiber5 app, and then I'll show you what all the different testing files do.
software development
software
technology
youtube
The Angular CLI generates all of the boilerplate code automatically, so so we'll start by looking at the Karma config file. Karma works by setting up a web server that will run all of your tests automatically every time a file changes.
You have some configuration options here if you want to customize that experience. You also have a protractor config file, which is specifically for end to end tests. Fact. End to end testing uses the browser to simulate how the end user sees your app, so it's completely decoupled from your main app code. That's why we have this e to e directory in the root of the project, and I'll show you how to use it in a future video. Now moving into the source directory, we have a test TS file. It's required by Karma to load all your spec files. You shouldn't really have to change anything in here.
software
software development
Now let's take a look at our first real test, which is the App component spec TS file. This just looks like a big jumble of code, so let's break the test down into its fundamental parts. The first part of any test is to describe the test suite. In Jasmine, you do this by using the describe keyword followed by whatever you're testing. The purple text represents Jasmine. The green represents what we're going to write. Fact. We write all the tests inside this describe block, each one starting with it.
So we're going to say it should be awesome. Then you'll write an expectation that verifies whether this is true or false. So with Jasmine, we could do something like expect component to be awesome. The end result is that you've described the behavior of your code in a way that can be easily read by a non programmer. Describing and validating your code in this way is the reason that testing is so effective at reducing bugs. Now we need something to test, so I'm going to start by generating this alert button component.
programming
logic
It's just a simple button that will toggle the visibility of this alert message whenever it's clicked. Fact. We'll start by testing its static values, but eventually, we'll use AngularFire 2 to populate its warning message. If if we look at the component typescript, I just have a couple of properties hard coded in here, and then I have a toggle method that will toggle the value of the hide content property. Fact. Then the template HTML just shows these properties and adds a button that will toggle the visibility of that message. The message is hidden by default, and that's something we're gonna test here in the 5 steps. So now let's set up our alert button spec from scratch. The first thing we're going to do is import Angular's testing utilities And then we're going to describe our test suite, which is the Angular button component. At this point, we're going to declare a variable for the fixture, and a fixture is just the test environment for this component. So it provides access to the component itself as well as its debug element, which is its rendered HTML. Fact. Now before each spec, we need to set up a test bed, which is just an NG module specific for this testing environment. The most simple example is just an isolated test of the component itself and that's where we're going to start, but this will get increasingly more complex. If you wanna compile the components HTML and CSS, then you'll call this compile components method after the test bed. After the test bed's been compiled, we can then set up a few variables here that we'll actually use for testing. We can test the component directly or we can test its rendered HTML via the debug element. And lastly, we'll run Angular change detection before each of these tests, but you could test things before change detection as well.
Now we're ready to write the first spec. The first thing we'll test is whether or not the component is created successfully. So we can say it should create and then we'll expect component to be truthy. Just a quick side note, truthy means that something evaluates to true in a boolean context. Fix. It doesn't mean what you're testing is actually the primitive true value. This is one of the many Jasmine matchers, and I recommend going to the docs to get acquainted with all of them.
logic
quality assurance
logical reasoning
Now that we have our spec, we can just run ng test, and that'll bring up a browser window saying whether or not it passed or failed. Now I'm just gonna leave Karma running so we can see how it updates every time we write a new spec. The second spec is going to see whether or not the content message has a substring of warn. In this case, the content was just hard coded as a property on the component, so we can say component content to contain the string of warn. Fact. The to contain matcher will check for a substring, or if it was an array, it would check for an element in that array. Now if we save this file, you can see the Karma runner on the left will update with the spec, and it will be passing as well. So the actual message content is you will be warned. So let's see what happens if we use a Jasmine Matcher that looks for an exact match. Fact. This time, we'll get a failing test, and it's also going to tell us exactly why it failed. It expected the string of you have been warned to be warned, which would be false.
You can also rate specs based on logical numeric values. So let's say we have a severity level on the alert and we wanna see if it is greater than 2. In In this case, it's actually 423. So if we say expect component severity to be greater than 2, that should be a passing test.
measurement
statistics
So far, we've only tested properties on the component itself, but now let's see if it actually rendered properly in the DOM. So let's say it should have an h one tag of alert button. To do that, we use the debug element and it has a DSL that allows us to query elements in the DOM. So we would say query by the CSS of h one, Then we can get the native HTML element. At that point, we just have the string that's inside the h one tag, and then we can validate that it is the alert written text. So now let's move on to a spec that will tell us whether or not a function is doing what it's supposed to do. We wrote a toggle method earlier that toggles a Boolean variable. So we'll say it should toggle the message Boolean, and first, we'll expect the component hide content to be truthy because it's hidden by default. Fact. Then we can execute that toggle button method, then we'll run another expectation that this time the component hide content boolean is falsy. That one passes as well, so we know that our method is performing what it's supposed to perform. But what if that change happens asynchronously as many things do in Angular? Fact. Back in the component, I'm going to define a method called toggle async, which will run the toggle method after an RxJS timer of 500 milliseconds runs out. Fact. The spec is going to be it should toggle the message Boolean asynchronously, then we're going to wrap this in the fake async helper from Angular. This creates a fake Angular zone that we can use to test asynchronous activity. The test is exactly the same as the last one, but calls the toggle async method. Fact. As you can see here, it fails because Angular doesn't wait for the 500 milliseconds to run out before testing that property. We also have a tick utility that we can use here in the fake async block. And so if we set that to 499 milliseconds, you can see here that we still get a failing test. Fact. The timer we set is 500 milliseconds, so if we add just one more millisecond to it, then the test will pass. That That gives you a few basic examples of Angular component testing, but now let's add a service to the mix using AngularFire 2. What we're going to do is create a service that returns an observable from the Firebase real time database, and that's going to replace the content that we had hard coded in the component before. If you're not familiar with AngularFire 2, make sure to follow the setup instructions on the main documentation. You also need to have a Firebase account. And inside the real time database, I have an alerts node with a test alert that says, you have been warned. Then I am going to generate a service with the CLI, And you can test your service directly, but for this video, we're just gonna focus on the component.
The service itself is very simple. We just add AngularFire database to the constructor, And then we'll set up one method in here called get content, which will retrieve that message from the database as an observable. When running your tests, You don't wanna actually use live data from the real back end. You should only simulate how that back end data would be returned by using what's called a stub. Fact. A stub is simply a method that returns some data in a way that's predictable and reproducible.
databases
data
So what I'm doing here is setting up a variable called Service stub. Fact. It's going to be an object that has a function in it that returns the observable in the same form that we'd expect back from Firebase. Fact. So the Get Content property is a function that returns an observable of the message, you have been warned. This gives us mock data that we can use to interact with the service without actually having to make a real request to Firebase. Then we can use this stub as a service by adding it to our test bed in the providers array. But instead of providing a live service, we do an object that has provide with the message service and then use value with our service stub.
This tells the test environment to use the stub instead of the actual live data. At this point, all we have to do is write our spec, and it should return this observable like we would expect. This time, we'll say it should have message content defined from an observable. And then what we'll do is subscribe to that observable and put our expectations inside the scribe block. We expect the content to be defined, and to be you have been warned. This is the easiest way to test mock data from a service, but it is limited in certain respects. For example, we can't tell how many times this method has been called, which might be important if you have a method that is not idempotent.
programming
documentation
modeling
data
data analysis
To address this, I'm going to stub our service using a different method called a Spy. This time, we're going to actually use the live service, so So we're going to need to set up our test bed with AngularFire 2. Then I'll set another variable for our service and another one for the Spy. From there, I'm going to add AngularFire 2 to the import section of the test bed. And then in the provider section, I'll take out the stub and add the live service to it. Fact. Then we can get rid of our previous service stub, and then we'll set up the Spy here, which comes from Jasmine. We can call Spy on and then pass it fact. The main service class as well as the method that we wanna monitor. So in this case, it's going to be our Get Content method. We still don't want to use any live data from Firebase, so what we do is tell our Spy to return a value of an observable of the message. What this is going to do is allow us to see whenever this method has been called and with what arguments it was called with, and it's never going to actually make a live request so it just stubs the return value. And to get the service class, we call debug element injector get with the message service. Fact. So our SPY is ready to go. Now we can just jump down and write our next spec. This time, I wanna make sure that the method is only called once and I wanna make sure that the view is updated with the corresponding observable data. So we can make sure our service method was called by calling expect spy to have been called. Then we can see how many times it was called by calling spies calls all, which is an array. And then we can test the length of that array, and it should be 1. So we'll say 2 equal 1. Then we're also unwrapping an Observable in the HTML, so I wanna make sure that this method results in an observable that gets rendered in the HTML itself. So we'll use query on the debug element to get the message body. Then we can look at the native element inner text, and that should be the message you have been warned.
So we can just call to contain warn to verify that. Fact. Then we can go ahead and save it and it's going to run our spec and it passes as expected. The spy can do a whole bunch of other stuff too, like see where the method was called and with which arguments.
security
So check out the Jasmine docs for more information on that.
That's it for Angular component testing basics. If this video helped you, please like and subscribe. And if you want to learn more advanced concepts, consider becoming a pro subscriber at angularfirebase.com. You'll get a whole bunch of exclusive content, 1 on 1 project support via Slack and a free copy of my book. Thanks for watching, and I'll see you soon.
youtube
websites
Test driven development is the single most powerful tool you have for preventing bugs within your application. That's not just my opinion, but it's a scientifically proven fact. In exchange for effort and productivity, you get better quality software that is more maintainable long term. Lucky for you, Angular comes built in with Jasmine and Karma, so testing is really easy to get started with. In this video, I'll give you a tour of Angular's testing tools and show you how to deal with third party dependencies like Firebase. F If you're new to the channel, make sure to subscribe, and you can always get the full source code on angularfirebase.com. The first thing I'm going to do is generate a brand new Angular Fiber5 app, and then I'll show you what all the different testing files do. The Angular CLI generates all of the boilerplate code automatically, so so we'll start by looking at the Karma config file. Karma works by setting up a web server that will run all of your tests automatically every time a file changes. You have some configuration options here if you want to customize that experience. You also have a protractor config file, which is specifically for end to end tests. Fact. End to end testing uses the browser to simulate how the end user sees your app, so it's completely decoupled from your main app code. That's why we have this e to e directory in the root of the project, and I'll show you how to use it in a future video. Now moving into the source directory, we have a test TS file. It's required by Karma to load all your spec files. You shouldn't really have to change anything in here. Now let's take a look at our first real test, which is the App component spec TS file. This just looks like a big jumble of code, so let's break the test down into its fundamental parts. The first part of any test is to describe the test suite. In Jasmine, you do this by using the describe keyword followed by whatever you're testing. The purple text represents Jasmine. The green represents what we're going to write. Fact. We write all the tests inside this describe block, each one starting with it. So we're going to say it should be awesome. Then you'll write an expectation that verifies whether this is true or false. So with Jasmine, we could do something like expect component to be awesome. The end result is that you've described the behavior of your code in a way that can be easily read by a non programmer. Describing and validating your code in this way is the reason that testing is so effective at reducing bugs. Now we need something to test, so I'm going to start by generating this alert button component. It's just a simple button that will toggle the visibility of this alert message whenever it's clicked. Fact. We'll start by testing its static values, but eventually, we'll use AngularFire 2 to populate its warning message. If if we look at the component typescript, I just have a couple of properties hard coded in here, and then I have a toggle method that will toggle the value of the hide content property. Fact. Then the template HTML just shows these properties and adds a button that will toggle the visibility of that message. The message is hidden by default, and that's something we're gonna test here in the 5 steps. So now let's set up our alert button spec from scratch. The first thing we're going to do is import Angular's testing utilities And then we're going to describe our test suite, which is the Angular button component. At this point, we're going to declare a variable for the fixture, and a fixture is just the test environment for this component. So it provides access to the component itself as well as its debug element, which is its rendered HTML. Fact. Now before each spec, we need to set up a test bed, which is just an NG module specific for this testing environment. The most simple example is just an isolated test of the component itself and that's where we're going to start, but this will get increasingly more complex. If you wanna compile the components HTML and CSS, then you'll call this compile components method after the test bed. After the test bed's been compiled, we can then set up a few variables here that we'll actually use for testing. We can test the component directly or we can test its rendered HTML via the debug element. And lastly, we'll run Angular change detection before each of these tests, but you could test things before change detection as well. Now we're ready to write the first spec. The first thing we'll test is whether or not the component is created successfully. So we can say it should create and then we'll expect component to be truthy. Just a quick side note, truthy means that something evaluates to true in a boolean context. Fix. It doesn't mean what you're testing is actually the primitive true value. This is one of the many Jasmine matchers, and I recommend going to the docs to get acquainted with all of them. Now that we have our spec, we can just run ng test, and that'll bring up a browser window saying whether or not it passed or failed. Now I'm just gonna leave Karma running so we can see how it updates every time we write a new spec. The second spec is going to see whether or not the content message has a substring of warn. In this case, the content was just hard coded as a property on the component, so we can say component content to contain the string of warn. Fact. The to contain matcher will check for a substring, or if it was an array, it would check for an element in that array. Now if we save this file, you can see the Karma runner on the left will update with the spec, and it will be passing as well. So the actual message content is you will be warned. So let's see what happens if we use a Jasmine Matcher that looks for an exact match. Fact. This time, we'll get a failing test, and it's also going to tell us exactly why it failed. It expected the string of you have been warned to be warned, which would be false. You can also rate specs based on logical numeric values. So let's say we have a severity level on the alert and we wanna see if it is greater than 2. In In this case, it's actually 423. So if we say expect component severity to be greater than 2, that should be a passing test. So far, we've only tested properties on the component itself, but now let's see if it actually rendered properly in the DOM. So let's say it should have an h one tag of alert button. To do that, we use the debug element and it has a DSL that allows us to query elements in the DOM. So we would say query by the CSS of h one, Then we can get the native HTML element. At that point, we just have the string that's inside the h one tag, and then we can validate that it is the alert written text. So now let's move on to a spec that will tell us whether or not a function is doing what it's supposed to do. We wrote a toggle method earlier that toggles a Boolean variable. So we'll say it should toggle the message Boolean, and first, we'll expect the component hide content to be truthy because it's hidden by default. Fact. Then we can execute that toggle button method, then we'll run another expectation that this time the component hide content boolean is falsy. That one passes as well, so we know that our method is performing what it's supposed to perform. But what if that change happens asynchronously as many things do in Angular? Fact. Back in the component, I'm going to define a method called toggle async, which will run the toggle method after an RxJS timer of 500 milliseconds runs out. Fact. The spec is going to be it should toggle the message Boolean asynchronously, then we're going to wrap this in the fake async helper from Angular. This creates a fake Angular zone that we can use to test asynchronous activity. The test is exactly the same as the last one, but calls the toggle async method. Fact. As you can see here, it fails because Angular doesn't wait for the 500 milliseconds to run out before testing that property. We also have a tick utility that we can use here in the fake async block. And so if we set that to 499 milliseconds, you can see here that we still get a failing test. Fact. The timer we set is 500 milliseconds, so if we add just one more millisecond to it, then the test will pass. That That gives you a few basic examples of Angular component testing, but now let's add a service to the mix using AngularFire 2. What we're going to do is create a service that returns an observable from the Firebase real time database, and that's going to replace the content that we had hard coded in the component before. If you're not familiar with AngularFire 2, make sure to follow the setup instructions on the main documentation. You also need to have a Firebase account. And inside the real time database, I have an alerts node with a test alert that says, you have been warned. Then I am going to generate a service with the CLI, And you can test your service directly, but for this video, we're just gonna focus on the component. The service itself is very simple. We just add AngularFire database to the constructor, And then we'll set up one method in here called get content, which will retrieve that message from the database as an observable. When running your tests, You don't wanna actually use live data from the real back end. You should only simulate how that back end data would be returned by using what's called a stub. Fact. A stub is simply a method that returns some data in a way that's predictable and reproducible. So what I'm doing here is setting up a variable called Service stub. Fact. It's going to be an object that has a function in it that returns the observable in the same form that we'd expect back from Firebase. Fact. So the Get Content property is a function that returns an observable of the message, you have been warned. This gives us mock data that we can use to interact with the service without actually having to make a real request to Firebase. Then we can use this stub as a service by adding it to our test bed in the providers array. But instead of providing a live service, we do an object that has provide with the message service and then use value with our service stub. This tells the test environment to use the stub instead of the actual live data. At this point, all we have to do is write our spec, and it should return this observable like we would expect. This time, we'll say it should have message content defined from an observable. And then what we'll do is subscribe to that observable and put our expectations inside the scribe block. We expect the content to be defined, and to be you have been warned. This is the easiest way to test mock data from a service, but it is limited in certain respects. For example, we can't tell how many times this method has been called, which might be important if you have a method that is not idempotent. To address this, I'm going to stub our service using a different method called a Spy. This time, we're going to actually use the live service, so So we're going to need to set up our test bed with AngularFire 2. Then I'll set another variable for our service and another one for the Spy. From there, I'm going to add AngularFire 2 to the import section of the test bed. And then in the provider section, I'll take out the stub and add the live service to it. Fact. Then we can get rid of our previous service stub, and then we'll set up the Spy here, which comes from Jasmine. We can call Spy on and then pass it fact. The main service class as well as the method that we wanna monitor. So in this case, it's going to be our Get Content method. We still don't want to use any live data from Firebase, so what we do is tell our Spy to return a value of an observable of the message. What this is going to do is allow us to see whenever this method has been called and with what arguments it was called with, and it's never going to actually make a live request so it just stubs the return value. And to get the service class, we call debug element injector get with the message service. Fact. So our SPY is ready to go. Now we can just jump down and write our next spec. This time, I wanna make sure that the method is only called once and I wanna make sure that the view is updated with the corresponding observable data. So we can make sure our service method was called by calling expect spy to have been called. Then we can see how many times it was called by calling spies calls all, which is an array. And then we can test the length of that array, and it should be 1. So we'll say 2 equal 1. Then we're also unwrapping an Observable in the HTML, so I wanna make sure that this method results in an observable that gets rendered in the HTML itself. So we'll use query on the debug element to get the message body. Then we can look at the native element inner text, and that should be the message you have been warned. So we can just call to contain warn to verify that. Fact. Then we can go ahead and save it and it's going to run our spec and it passes as expected. The spy can do a whole bunch of other stuff too, like see where the method was called and with which arguments. So check out the Jasmine docs for more information on that. That's it for Angular component testing basics. If this video helped you, please like and subscribe. And if you want to learn more advanced concepts, consider becoming a pro subscriber at angularfirebase.com. You'll get a whole bunch of exclusive content, 1 on 1 project support via Slack and a free copy of my book. Thanks for watching, and I'll see you soon.
Test
test
driven
driven
development
development
is
is
the
the
single
single
most
most
powerful
powerful
tool
tool
you
you
have
have
for
for
preventing
preventing
bugs
bugs
within
within
your
your
application.
application
That's
that's
not
not
just
just
my
my
opinion,
opinion
but
but
it's
it's
a
a
scientifically
scientifically
proven
proven
fact.
fact
In
in
exchange
exchange
for
for
effort
effort
and
and
productivity,
productivity
you
you
get
get
better
better
quality
quality
software
software
that
that
is
is
more
more
maintainable
maintainable
long
long
term.
term
Lucky
lucky
for
for
you,
you
Angular
angular
comes
comes
built
built
in
in
with
with
Jasmine
jasmine
and
and
Karma,
karma
so
so
testing
testing
is
is
really
really
easy
easy
to
to
get
get
started
started
with.
with
In
in
this
this
video,
video
I'll
i'll
give
give
you
you
a
a
tour
tour
of
of
Angular's
angular's
testing
testing
tools
tools
and
and
show
show
you
you
how
how
to
to
deal
deal
with
with
third
third
party
party
dependencies
dependencies
like
like
Firebase.
firebase
F
f
If
if
you're
you're
new
new
to
to
the
the
channel,
channel
make
make
sure
sure
to
to
subscribe,
subscribe
and
and
you
you
can
can
always
always
get
get
the
the
full
full
source
source
code
code
on
on
angularfirebase.com.
angularfirebase.com
The
the
first
first
thing
thing
I'm
i'm
going
going
to
to
do
do
is
is
generate
generate
a
a
brand
brand
new
new
Angular
angular
Fiber5
fiber5
app,
app
and
and
then
then
I'll
i'll
show
show
you
you
what
what
all
all
the
the
different
different
testing
testing
files
files
do.
do
The
the
Angular
angular
CLI
cli
generates
generates
all
all
of
of
the
the
boilerplate
boilerplate
code
code
automatically,
automatically
so
so
so
so
we'll
we'll
start
start
by
by
looking
looking
at
at
the
the
Karma
karma
config
config
file.
file
Karma
karma
works
works
by
by
setting
setting
up
up
a
a
web
web
server
server
that
that
will
will
run
run
all
all
of
of
your
your
tests
tests
automatically
automatically
every
every
time
time
a
a
file
file
changes.
changes
You
you
have
have
some
some
configuration
configuration
options
options
here
here
if
if
you
you
want
want
to
to
customize
customize
that
that
experience.
experience
You
you
also
also
have
have
a
a
protractor
protractor
config
config
file,
file
which
which
is
is
specifically
specifically
for
for
end
end
to
to
end
end
tests.
tests
Fact.
fact
End
end
to
to
end
end
testing
testing
uses
uses
the
the
browser
browser
to
to
simulate
simulate
how
how
the
the
end
end
user
user
sees
sees
your
your
app,
app
so
so
it's
it's
completely
completely
decoupled
decoupled
from
from
your
your
main
main
app
app
code.
code
That's
that's
why
why
we
we
have
have
this
this
e
e
to
to
e
e
directory
directory
in
in
the
the
root
root
of
of
the
the
project,
project
and
and
I'll
i'll
show
show
you
you
how
how
to
to
use
use
it
it
in
in
a
a
future
future
video.
video
Now
now
moving
moving
into
into
the
the
source
source
directory,
directory
we
we
have
have
a
a
test
test
TS
ts
file.
file
It's
it's
required
required
by
by
Karma
karma
to
to
load
load
all
all
your
your
spec
spec
files.
files
You
you
shouldn't
shouldn't
really
really
have
have
to
to
change
change
anything
anything
in
in
here.
here
Now
now
let's
let's
take
take
a
a
look
look
at
at
our
our
first
first
real
real
test,
test
which
which
is
is
the
the
App
app
component
component
spec
spec
TS
ts
file.
file
This
this
just
just
looks
looks
like
like
a
a
big
big
jumble
jumble
of
of
code,
code
so
so
let's
let's
break
break
the
the
test
test
down
down
into
into
its
its
fundamental
fundamental
parts.
parts
The
the
first
first
part
part
of
of
any
any
test
test
is
is
to
to
describe
describe
the
the
test
test
suite.
suite
In
in
Jasmine,
jasmine
you
you
do
do
this
this
by
by
using
using
the
the
describe
describe
keyword
keyword
followed
followed
by
by
whatever
whatever
you're
you're
testing.
testing
The
the
purple
purple
text
text
represents
represents
Jasmine.
jasmine
The
the
green
green
represents
represents
what
what
we're
we're
going
going
to
to
write.
write
Fact.
fact
We
we
write
write
all
all
the
the
tests
tests
inside
inside
this
this
describe
describe
block,
block
each
each
one
one
starting
starting
with
with
it.
it
So
so
we're
we're
going
going
to
to
say
say
it
it
should
should
be
be
awesome.
awesome
Then
then
you'll
you'll
write
write
an
an
expectation
expectation
that
that
verifies
verifies
whether
whether
this
this
is
is
true
true
or
or
false.
false
So
so
with
with
Jasmine,
jasmine
we
we
could
could
do
do
something
something
like
like
expect
expect
component
component
to
to
be
be
awesome.
awesome
The
the
end
end
result
result
is
is
that
that
you've
you've
described
described
the
the
behavior
behavior
of
of
your
your
code
code
in
in
a
a
way
way
that
that
can
can
be
be
easily
easily
read
read
by
by
a
a
non
non
programmer.
programmer
Describing
describing
and
and
validating
validating
your
your
code
code
in
in
this
this
way
way
is
is
the
the
reason
reason
that
that
testing
testing
is
is
so
so
effective
effective
at
at
reducing
reducing
bugs.
bugs
Now
now
we
we
need
need
something
something
to
to
test,
test
so
so
I'm
i'm
going
going
to
to
start
start
by
by
generating
generating
this
this
alert
alert
button
button
component.
component
It's
it's
just
just
a
a
simple
simple
button
button
that
that
will
will
toggle
toggle
the
the
visibility
visibility
of
of
this
this
alert
alert
message
message
whenever
whenever
it's
it's
clicked.
clicked
Fact.
fact
We'll
we'll
start
start
by
by
testing
testing
its
its
static
static
values,
values
but
but
eventually,
eventually
we'll
we'll
use
use
AngularFire
angularfire
2
2
to
to
populate
populate
its
its
warning
warning
message.
message
If
if
if
if
we
we
look
look
at
at
the
the
component
component
typescript,
typescript
I
i
just
just
have
have
a
a
couple
couple
of
of
properties
properties
hard
hard
coded
coded
in
in
here,
here
and
and
then
then
I
i
have
have
a
a
toggle
toggle
method
method
that
that
will
will
toggle
toggle
the
the
value
value
of
of
the
the
hide
hide
content
content
property.
property
Fact.
fact
Then
then
the
the
template
template
HTML
html
just
just
shows
shows
these
these
properties
properties
and
and
adds
adds
a
a
button
button
that
that
will
will
toggle
toggle
the
the
visibility
visibility
of
of
that
that
message.
message
The
the
message
message
is
is
hidden
hidden
by
by
default,
default
and
and
that's
that's
something
something
we're
we're
gonna
gonna
test
test
here
here
in
in
the
the
5
5
steps.
steps
So
so
now
now
let's
let's
set
set
up
up
our
our
alert
alert
button
button
spec
spec
from
from
scratch.
scratch
The
the
first
first
thing
thing
we're
we're
going
going
to
to
do
do
is
is
import
import
Angular's
angular's
testing
testing
utilities
utilities
And
and
then
then
we're
we're
going
going
to
to
describe
describe
our
our
test
test
suite,
suite
which
which
is
is
the
the
Angular
angular
button
button
component.
component
At
at
this
this
point,
point
we're
we're
going
going
to
to
declare
declare
a
a
variable
variable
for
for
the
the
fixture,
fixture
and
and
a
a
fixture
fixture
is
is
just
just
the
the
test
test
environment
environment
for
for
this
this
component.
component
So
so
it
it
provides
provides
access
access
to
to
the
the
component
component
itself
itself
as
as
well
well
as
as
its
its
debug
debug
element,
element
which
which
is
is
its
its
rendered
rendered
HTML.
html
Fact.
fact
Now
now
before
before
each
each
spec,
spec
we
we
need
need
to
to
set
set
up
up
a
a
test
test
bed,
bed
which
which
is
is
just
just
an
an
NG
ng
module
module
specific
specific
for
for
this
this
testing
testing
environment.
environment
The
the
most
most
simple
simple
example
example
is
is
just
just
an
an
isolated
isolated
test
test
of
of
the
the
component
component
itself
itself
and
and
that's
that's
where
where
we're
we're
going
going
to
to
start,
start
but
but
this
this
will
will
get
get
increasingly
increasingly
more
more
complex.
complex
If
if
you
you
wanna
wanna
compile
compile
the
the
components
components
HTML
html
and
and
CSS,
css
then
then
you'll
you'll
call
call
this
this
compile
compile
components
components
method
method
after
after
the
the
test
test
bed.
bed
After
after
the
the
test
test
bed's
bed's
been
been
compiled,
compiled
we
we
can
can
then
then
set
set
up
up
a
a
few
few
variables
variables
here
here
that
that
we'll
we'll
actually
actually
use
use
for
for
testing.
testing
We
we
can
can
test
test
the
the
component
component
directly
directly
or
or
we
we
can
can
test
test
its
its
rendered
rendered
HTML
html
via
via
the
the
debug
debug
element.
element
And
and
lastly,
lastly
we'll
we'll
run
run
Angular
angular
change
change
detection
detection
before
before
each
each
of
of
these
these
tests,
tests
but
but
you
you
could
could
test
test
things
things
before
before
change
change
detection
detection
as
as
well.
well
Now
now
we're
we're
ready
ready
to
to
write
write
the
the
first
first
spec.
spec
The
the
first
first
thing
thing
we'll
we'll
test
test
is
is
whether
whether
or
or
not
not
the
the
component
component
is
is
created
created
successfully.
successfully
So
so
we
we
can
can
say
say
it
it
should
should
create
create
and
and
then
then
we'll
we'll
expect
expect
component
component
to
to
be
be
truthy.
truthy
Just
just
a
a
quick
quick
side
side
note,
note
truthy
truthy
means
means
that
that
something
something
evaluates
evaluates
to
to
true
true
in
in
a
a
boolean
boolean
context.
context
Fix.
fix
It
it
doesn't
doesn't
mean
mean
what
what
you're
you're
testing
testing
is
is
actually
actually
the
the
primitive
primitive
true
true
value.
value
This
this
is
is
one
one
of
of
the
the
many
many
Jasmine
jasmine
matchers,
matchers
and
and
I
i
recommend
recommend
going
going
to
to
the
the
docs
docs
to
to
get
get
acquainted
acquainted
with
with
all
all
of
of
them.
them
Now
now
that
that
we
we
have
have
our
our
spec,
spec
we
we
can
can
just
just
run
run
ng
ng
test,
test
and
and
that'll
that'll
bring
bring
up
up
a
a
browser
browser
window
window
saying
saying
whether
whether
or
or
not
not
it
it
passed
passed
or
or
failed.
failed
Now
now
I'm
i'm
just
just
gonna
gonna
leave
leave
Karma
karma
running
running
so
so
we
we
can
can
see
see
how
how
it
it
updates
updates
every
every
time
time
we
we
write
write
a
a
new
new
spec.
spec
The
the
second
second
spec
spec
is
is
going
going
to
to
see
see
whether
whether
or
or
not
not
the
the
content
content
message
message
has
has
a
a
substring
substring
of
of
warn.
warn
In
in
this
this
case,
case
the
the
content
content
was
was
just
just
hard
hard
coded
coded
as
as
a
a
property
property
on
on
the
the
component,
component
so
so
we
we
can
can
say
say
component
component
content
content
to
to
contain
contain
the
the
string
string
of
of
warn.
warn
Fact.
fact
The
the
to
to
contain
contain
matcher
matcher
will
will
check
check
for
for
a
a
substring,
substring
or
or
if
if
it
it
was
was
an
an
array,
array
it
it
would
would
check
check
for
for
an
an
element
element
in
in
that
that
array.
array
Now
now
if
if
we
we
save
save
this
this
file,
file
you
you
can
can
see
see
the
the
Karma
karma
runner
runner
on
on
the
the
left
left
will
will
update
update
with
with
the
the
spec,
spec
and
and
it
it
will
will
be
be
passing
passing
as
as
well.
well
So
so
the
the
actual
actual
message
message
content
content
is
is
you
you
will
will
be
be
warned.
warned
So
so
let's
let's
see
see
what
what
happens
happens
if
if
we
we
use
use
a
a
Jasmine
jasmine
Matcher
matcher
that
that
looks
looks
for
for
an
an
exact
exact
match.
match
Fact.
fact
This
this
time,
time
we'll
we'll
get
get
a
a
failing
failing
test,
test
and
and
it's
it's
also
also
going
going
to
to
tell
tell
us
us
exactly
exactly
why
why
it
it
failed.
failed
It
it
expected
expected
the
the
string
string
of
of
you
you
have
have
been
been
warned
warned
to
to
be
be
warned,
warned
which
which
would
would
be
be
false.
false
You
you
can
can
also
also
rate
rate
specs
specs
based
based
on
on
logical
logical
numeric
numeric
values.
values
So
so
let's
let's
say
say
we
we
have
have
a
a
severity
severity
level
level
on
on
the
the
alert
alert
and
and
we
we
wanna
wanna
see
see
if
if
it
it
is
is
greater
greater
than
than
2.
2
In
in
In
in
this
this
case,
case
it's
it's
actually
actually
423.
423
So
so
if
if
we
we
say
say
expect
expect
component
component
severity
severity
to
to
be
be
greater
greater
than
than
2,
2
that
that
should
should
be
be
a
a
passing
passing
test.
test
So
so
far,
far
we've
we've
only
only
tested
tested
properties
properties
on
on
the
the
component
component
itself,
itself
but
but
now
now
let's
let's
see
see
if
if
it
it
actually
actually
rendered
rendered
properly
properly
in
in
the
the
DOM.
dom
So
so
let's
let's
say
say
it
it
should
should
have
have
an
an
h
h
one
one
tag
tag
of
of
alert
alert
button.
button
To
to
do
do
that,
that
we
we
use
use
the
the
debug
debug
element
element
and
and
it
it
has
has
a
a
DSL
dsl
that
that
allows
allows
us
us
to
to
query
query
elements
elements
in
in
the
the
DOM.
dom
So
so
we
we
would
would
say
say
query
query
by
by
the
the
CSS
css
of
of
h
h
one,
one
Then
then
we
we
can
can
get
get
the
the
native
native
HTML
html
element.
element
At
at
that
that
point,
point
we
we
just
just
have
have
the
the
string
string
that's
that's
inside
inside
the
the
h
h
one
one
tag,
tag
and
and
then
then
we
we
can
can
validate
validate
that
that
it
it
is
is
the
the
alert
alert
written
written
text.
text
So
so
now
now
let's
let's
move
move
on
on
to
to
a
a
spec
spec
that
that
will
will
tell
tell
us
us
whether
whether
or
or
not
not
a
a
function
function
is
is
doing
doing
what
what
it's
it's
supposed
supposed
to
to
do.
do
We
we
wrote
wrote
a
a
toggle
toggle
method
method
earlier
earlier
that
that
toggles
toggles
a
a
Boolean
boolean
variable.
variable
So
so
we'll
we'll
say
say
it
it
should
should
toggle
toggle
the
the
message
message
Boolean,
boolean
and
and
first,
first
we'll
we'll
expect
expect
the
the
component
component
hide
hide
content
content
to
to
be
be
truthy
truthy
because
because
it's
it's
hidden
hidden
by
by
default.
default
Fact.
fact
Then
then
we
we
can
can
execute
execute
that
that
toggle
toggle
button
button
method,
method
then
then
we'll
we'll
run
run
another
another
expectation
expectation
that
that
this
this
time
time
the
the
component
component
hide
hide
content
content
boolean
boolean
is
is
falsy.
falsy
That
that
one
one
passes
passes
as
as
well,
well
so
so
we
we
know
know
that
that
our
our
method
method
is
is
performing
performing
what
what
it's
it's
supposed
supposed
to
to
perform.
perform
But
but
what
what
if
if
that
that
change
change
happens
happens
asynchronously
asynchronously
as
as
many
many
things
things
do
do
in
in
Angular?
angular
Fact.
fact
Back
back
in
in
the
the
component,
component
I'm
i'm
going
going
to
to
define
define
a
a
method
method
called
called
toggle
toggle
async,
async
which
which
will
will
run
run
the
the
toggle
toggle
method
method
after
after
an
an
RxJS
rxjs
timer
timer
of
of
500
500
milliseconds
milliseconds
runs
runs
out.
out
Fact.
fact
The
the
spec
spec
is
is
going
going
to
to
be
be
it
it
should
should
toggle
toggle
the
the
message
message
Boolean
boolean
asynchronously,
asynchronously
then
then
we're
we're
going
going
to
to
wrap
wrap
this
this
in
in
the
the
fake
fake
async
async
helper
helper
from
from
Angular.
angular
This
this
creates
creates
a
a
fake
fake
Angular
angular
zone
zone
that
that
we
we
can
can
use
use
to
to
test
test
asynchronous
asynchronous
activity.
activity
The
the
test
test
is
is
exactly
exactly
the
the
same
same
as
as
the
the
last
last
one,
one
but
but
calls
calls
the
the
toggle
toggle
async
async
method.
method
Fact.
fact
As
as
you
you
can
can
see
see
here,
here
it
it
fails
fails
because
because
Angular
angular
doesn't
doesn't
wait
wait
for
for
the
the
500
500
milliseconds
milliseconds
to
to
run
run
out
out
before
before
testing
testing
that
that
property.
property
We
we
also
also
have
have
a
a
tick
tick
utility
utility
that
that
we
we
can
can
use
use
here
here
in
in
the
the
fake
fake
async
async
block.
block
And
and
so
so
if
if
we
we
set
set
that
that
to
to
499
499
milliseconds,
milliseconds
you
you
can
can
see
see
here
here
that
that
we
we
still
still
get
get
a
a
failing
failing
test.
test
Fact.
fact
The
the
timer
timer
we
we
set
set
is
is
500
500
milliseconds,
milliseconds
so
so
if
if
we
we
add
add
just
just
one
one
more
more
millisecond
millisecond
to
to
it,
it
then
then
the
the
test
test
will
will
pass.
pass
That
that
That
that
gives
gives
you
you
a
a
few
few
basic
basic
examples
examples
of
of
Angular
angular
component
component
testing,
testing
but
but
now
now
let's
let's
add
add
a
a
service
service
to
to
the
the
mix
mix
using
using
AngularFire
angularfire
2.
2
What
what
we're
we're
going
going
to
to
do
do
is
is
create
create
a
a
service
service
that
that
returns
returns
an
an
observable
observable
from
from
the
the
Firebase
firebase
real
real
time
time
database,
database
and
and
that's
that's
going
going
to
to
replace
replace
the
the
content
content
that
that
we
we
had
had
hard
hard
coded
coded
in
in
the
the
component
component
before.
before
If
if
you're
you're
not
not
familiar
familiar
with
with
AngularFire
angularfire
2,
2
make
make
sure
sure
to
to
follow
follow
the
the
setup
setup
instructions
instructions
on
on
the
the
main
main
documentation.
documentation
You
you
also
also
need
need
to
to
have
have
a
a
Firebase
firebase
account.
account
And
and
inside
inside
the
the
real
real
time
time
database,
database
I
i
have
have
an
an
alerts
alerts
node
node
with
with
a
a
test
test
alert
alert
that
that
says,
says
you
you
have
have
been
been
warned.
warned
Then
then
I
i
am
am
going
going
to
to
generate
generate
a
a
service
service
with
with
the
the
CLI,
cli
And
and
you
you
can
can
test
test
your
your
service
service
directly,
directly
but
but
for
for
this
this
video,
video
we're
we're
just
just
gonna
gonna
focus
focus
on
on
the
the
component.
component
The
the
service
service
itself
itself
is
is
very
very
simple.
simple
We
we
just
just
add
add
AngularFire
angularfire
database
database
to
to
the
the
constructor,
constructor
And
and
then
then
we'll
we'll
set
set
up
up
one
one
method
method
in
in
here
here
called
called
get
get
content,
content
which
which
will
will
retrieve
retrieve
that
that
message
message
from
from
the
the
database
database
as
as
an
an
observable.
observable
When
when
running
running
your
your
tests,
tests
You
you
don't
don't
wanna
wanna
actually
actually
use
use
live
live
data
data
from
from
the
the
real
real
back
back
end.
end
You
you
should
should
only
only
simulate
simulate
how
how
that
that
back
back
end
end
data
data
would
would
be
be
returned
returned
by
by
using
using
what's
what's
called
called
a
a
stub.
stub
Fact.
fact
A
a
stub
stub
is
is
simply
simply
a
a
method
method
that
that
returns
returns
some
some
data
data
in
in
a
a
way
way
that's
that's
predictable
predictable
and
and
reproducible.
reproducible
So
so
what
what
I'm
i'm
doing
doing
here
here
is
is
setting
setting
up
up
a
a
variable
variable
called
called
Service
service
stub.
stub
Fact.
fact
It's
it's
going
going
to
to
be
be
an
an
object
object
that
that
has
has
a
a
function
function
in
in
it
it
that
that
returns
returns
the
the
observable
observable
in
in
the
the
same
same
form
form
that
that
we'd
we'd
expect
expect
back
back
from
from
Firebase.
firebase
Fact.
fact
So
so
the
the
Get
get
Content
content
property
property
is
is
a
a
function
function
that
that
returns
returns
an
an
observable
observable
of
of
the
the
message,
message
you
you
have
have
been
been
warned.
warned
This
this
gives
gives
us
us
mock
mock
data
data
that
that
we
we
can
can
use
use
to
to
interact
interact
with
with
the
the
service
service
without
without
actually
actually
having
having
to
to
make
make
a
a
real
real
request
request
to
to
Firebase.
firebase
Then
then
we
we
can
can
use
use
this
this
stub
stub
as
as
a
a
service
service
by
by
adding
adding
it
it
to
to
our
our
test
test
bed
bed
in
in
the
the
providers
providers
array.
array
But
but
instead
instead
of
of
providing
providing
a
a
live
live
service,
service
we
we
do
do
an
an
object
object
that
that
has
has
provide
provide
with
with
the
the
message
message
service
service
and
and
then
then
use
use
value
value
with
with
our
our
service
service
stub.
stub
This
this
tells
tells
the
the
test
test
environment
environment
to
to
use
use
the
the
stub
stub
instead
instead
of
of
the
the
actual
actual
live
live
data.
data
At
at
this
this
point,
point
all
all
we
we
have
have
to
to
do
do
is
is
write
write
our
our
spec,
spec
and
and
it
it
should
should
return
return
this
this
observable
observable
like
like
we
we
would
would
expect.
expect
This
this
time,
time
we'll
we'll
say
say
it
it
should
should
have
have
message
message
content
content
defined
defined
from
from
an
an
observable.
observable
And
and
then
then
what
what
we'll
we'll
do
do
is
is
subscribe
subscribe
to
to
that
that
observable
observable
and
and
put
put
our
our
expectations
expectations
inside
inside
the
the
scribe
scribe
block.
block
We
we
expect
expect
the
the
content
content
to
to
be
be
defined,
defined
and
and
to
to
be
be
you
you
have
have
been
been
warned.
warned
This
this
is
is
the
the
easiest
easiest
way
way
to
to
test
test
mock
mock
data
data
from
from
a
a
service,
service
but
but
it
it
is
is
limited
limited
in
in
certain
certain
respects.
respects
For
for
example,
example
we
we
can't
can't
tell
tell
how
how
many
many
times
times
this
this
method
method
has
has
been
been
called,
called
which
which
might
might
be
be
important
important
if
if
you
you
have
have
a
a
method
method
that
that
is
is
not
not
idempotent.
idempotent
To
to
address
address
this,
this
I'm
i'm
going
going
to
to
stub
stub
our
our
service
service
using
using
a
a
different
different
method
method
called
called
a
a
Spy.
spy
This
this
time,
time
we're
we're
going
going
to
to
actually
actually
use
use
the
the
live
live
service,
service
so
so
So
so
we're
we're
going
going
to
to
need
need
to
to
set
set
up
up
our
our
test
test
bed
bed
with
with
AngularFire
angularfire
2.
2
Then
then
I'll
i'll
set
set
another
another
variable
variable
for
for
our
our
service
service
and
and
another
another
one
one
for
for
the
the
Spy.
spy
From
from
there,
there
I'm
i'm
going
going
to
to
add
add
AngularFire
angularfire
2
2
to
to
the
the
import
import
section
section
of
of
the
the
test
test
bed.
bed
And
and
then
then
in
in
the
the
provider
provider
section,
section
I'll
i'll
take
take
out
out
the
the
stub
stub
and
and
add
add
the
the
live
live
service
service
to
to
it.
it
Fact.
fact
Then
then
we
we
can
can
get
get
rid
rid
of
of
our
our
previous
previous
service
service
stub,
stub
and
and
then
then
we'll
we'll
set
set
up
up
the
the
Spy
spy
here,
here
which
which
comes
comes
from
from
Jasmine.
jasmine
We
we
can
can
call
call
Spy
spy
on
on
and
and
then
then
pass
pass
it
it
fact.
fact
The
the
main
main
service
service
class
class
as
as
well
well
as
as
the
the
method
method
that
that
we
we
wanna
wanna
monitor.
monitor
So
so
in
in
this
this
case,
case
it's
it's
going
going
to
to
be
be
our
our
Get
get
Content
content
method.
method
We
we
still
still
don't
don't
want
want
to
to
use
use
any
any
live
live
data
data
from
from
Firebase,
firebase
so
so
what
what
we
we
do
do
is
is
tell
tell
our
our
Spy
spy
to
to
return
return
a
a
value
value
of
of
an
an
observable
observable
of
of
the
the
message.
message
What
what
this
this
is
is
going
going
to
to
do
do
is
is
allow
allow
us
us
to
to
see
see
whenever
whenever
this
this
method
method
has
has
been
been
called
called
and
and
with
with
what
what
arguments
arguments
it
it
was
was
called
called
with,
with
and
and
it's
it's
never
never
going
going
to
to
actually
actually
make
make
a
a
live
live
request
request
so
so
it
it
just
just
stubs
stubs
the
the
return
return
value.
value
And
and
to
to
get
get
the
the
service
service
class,
class
we
we
call
call
debug
debug
element
element
injector
injector
get
get
with
with
the
the
message
message
service.
service
Fact.
fact
So
so
our
our
SPY
spy
is
is
ready
ready
to
to
go.
go
Now
now
we
we
can
can
just
just
jump
jump
down
down
and
and
write
write
our
our
next
next
spec.
spec
This
this
time,
time
I
i
wanna
wanna
make
make
sure
sure
that
that
the
the
method
method
is
is
only
only
called
called
once
once
and
and
I
i
wanna
wanna
make
make
sure
sure
that
that
the
the
view
view
is
is
updated
updated
with
with
the
the
corresponding
corresponding
observable
observable
data.
data
So
so
we
we
can
can
make
make
sure
sure
our
our
service
service
method
method
was
was
called
called
by
by
calling
calling
expect
expect
spy
spy
to
to
have
have
been
been
called.
called
Then
then
we
we
can
can
see
see
how
how
many
many
times
times
it
it
was
was
called
called
by
by
calling
calling
spies
spies
calls
calls
all,
all
which
which
is
is
an
an
array.
array
And
and
then
then
we
we
can
can
test
test
the
the
length
length
of
of
that
that
array,
array
and
and
it
it
should
should
be
be
1.
1
So
so
we'll
we'll
say
say
2
2
equal
equal
1.
1
Then
then
we're
we're
also
also
unwrapping
unwrapping
an
an
Observable
observable
in
in
the
the
HTML,
html
so
so
I
i
wanna
wanna
make
make
sure
sure
that
that
this
this
method
method
results
results
in
in
an
an
observable
observable
that
that
gets
gets
rendered
rendered
in
in
the
the
HTML
html
itself.
itself
So
so
we'll
we'll
use
use
query
query
on
on
the
the
debug
debug
element
element
to
to
get
get
the
the
message
message
body.
body
Then
then
we
we
can
can
look
look
at
at
the
the
native
native
element
element
inner
inner
text,
text
and
and
that
that
should
should
be
be
the
the
message
message
you
you
have
have
been
been
warned.
warned
So
so
we
we
can
can
just
just
call
call
to
to
contain
contain
warn
warn
to
to
verify
verify
that.
that
Fact.
fact
Then
then
we
we
can
can
go
go
ahead
ahead
and
and
save
save
it
it
and
and
it's
it's
going
going
to
to
run
run
our
our
spec
spec
and
and
it
it
passes
passes
as
as
expected.
expected
The
the
spy
spy
can
can
do
do
a
a
whole
whole
bunch
bunch
of
of
other
other
stuff
stuff
too,
too
like
like
see
see
where
where
the
the
method
method
was
was
called
called
and
and
with
with
which
which
arguments.
arguments
So
so
check
check
out
out
the
the
Jasmine
jasmine
docs
docs
for
for
more
more
information
information
on
on
that.
that
That's
that's
it
it
for
for
Angular
angular
component
component
testing
testing
basics.
basics
If
if
this
this
video
video
helped
helped
you,
you
please
please
like
like
and
and
subscribe.
subscribe
And
and
if
if
you
you
want
want
to
to
learn
learn
more
more
advanced
advanced
concepts,
concepts
consider
consider
becoming
becoming
a
a
pro
pro
subscriber
subscriber
at
at
angularfirebase.com.
angularfirebase.com
You'll
you'll
get
get
a
a
whole
whole
bunch
bunch
of
of
exclusive
exclusive
content,
content
1
1
on
on
1
1
project
project
support
support
via
via
Slack
slack
and
and
a
a
free
free
copy
copy
of
of
my
my
book.
book
Thanks
thanks
for
for
watching,
watching
and
and
I'll
i'll
see
see
you
you
soon.
soon
success
The speakers discuss the benefits of test driven development for preventing bugs in applications and provide a tour of Angular's testing tools. They then demonstrate a test suite for a test component, including a command line, alert button, and a test bed. They explain how to set up a test environment, generate a brand new Angular Fiber5 app, and use the test suite in various ways. They also discuss setting up a method called " toggle async" and adding a service to the mix using Angularhair 2. The service is created by setting up a variable called " refused to use live data" and using the service stub. The test run is then run to see if the method is used and if the return value is defined.
Angular Testing Quick Start
Test driven development is the single most powerful tool you have for preventing bugs within your application. That's not just my opinion, but it's a scientifically proven fact. In exchange for effort and productivity, you get better quality software that is more maintainable long term. Lucky for you, Angular comes built in with Jasmine and Karma, so testing is really easy to get started with. In this video, I'll give you a tour of Angular's testing tools and show you how to deal with third party dependencies like Firebase. F If you're new to the channel, make sure to subscribe, and you can always get the full source code on angularfirebase.com. The first thing I'm going to do is generate a brand new Angular Fiber5 app, and then I'll show you what all the different testing files do. The Angular CLI generates all of the boilerplate code automatically, so so we'll start by looking at the Karma config file. Karma works by setting up a web server that will run all of your tests automatically every time a file changes. You have some configuration options here if you want to customize that experience. You also have a protractor config file, which is specifically for end to end tests. Fact. End to end testing uses the browser to simulate how the end user sees your app, so it's completely decoupled from your main app code. That's why we have this e to e directory in the root of the project, and I'll show you how to use it in a future video. Now moving into the source directory, we have a test TS file. It's required by Karma to load all your spec files. You shouldn't really have to change anything in here. Now let's take a look at our first real test, which is the App component spec TS file. This just looks like a big jumble of code, so let's break the test down into its fundamental parts. The first part of any test is to describe the test suite. In Jasmine, you do this by using the describe keyword followed by whatever you're testing. The purple text represents Jasmine. The green represents what we're going to write. Fact. We write all the tests inside this describe block, each one starting with it. So we're going to say it should be awesome. Then you'll write an expectation that verifies whether this is true or false. So with Jasmine, we could do something like expect component to be awesome. The end result is that you've described the behavior of your code in a way that can be easily read by a non programmer. Describing and validating your code in this way is the reason that testing is so effective at reducing bugs. Now we need something to test, so I'm going to start by generating this alert button component. It's just a simple button that will toggle the visibility of this alert message whenever it's clicked. Fact. We'll start by testing its static values, but eventually, we'll use AngularFire 2 to populate its warning message. If if we look at the component typescript, I just have a couple of properties hard coded in here, and then I have a toggle method that will toggle the value of the hide content property. Fact. Then the template HTML just shows these properties and adds a button that will toggle the visibility of that message. The message is hidden by default, and that's something we're gonna test here in the 5 steps. So now let's set up our alert button spec from scratch. The first thing we're going to do is import Angular's testing utilities And then we're going to describe our test suite, which is the Angular button component. At this point, we're going to declare a variable for the fixture, and a fixture is just the test environment for this component. So it provides access to the component itself as well as its debug element, which is its rendered HTML. Fact. Now before each spec, we need to set up a test bed, which is just an NG module specific for this testing environment. The most simple example is just an isolated test of the component itself and that's where we're going to start, but this will get increasingly more complex. If you wanna compile the components HTML and CSS, then you'll call this compile components method after the test bed. After the test bed's been compiled, we can then set up a few variables here that we'll actually use for testing. We can test the component directly or we can test its rendered HTML via the debug element. And lastly, we'll run Angular change detection before each of these tests, but you could test things before change detection as well. Now we're ready to write the first spec. The first thing we'll test is whether or not the component is created successfully. So we can say it should create and then we'll expect component to be truthy. Just a quick side note, truthy means that something evaluates to true in a boolean context. Fix. It doesn't mean what you're testing is actually the primitive true value. This is one of the many Jasmine matchers, and I recommend going to the docs to get acquainted with all of them. Now that we have our spec, we can just run ng test, and that'll bring up a browser window saying whether or not it passed or failed. Now I'm just gonna leave Karma running so we can see how it updates every time we write a new spec. The second spec is going to see whether or not the content message has a substring of warn. In this case, the content was just hard coded as a property on the component, so we can say component content to contain the string of warn. Fact. The to contain matcher will check for a substring, or if it was an array, it would check for an element in that array. Now if we save this file, you can see the Karma runner on the left will update with the spec, and it will be passing as well. So the actual message content is you will be warned. So let's see what happens if we use a Jasmine Matcher that looks for an exact match. Fact. This time, we'll get a failing test, and it's also going to tell us exactly why it failed. It expected the string of you have been warned to be warned, which would be false. You can also rate specs based on logical numeric values. So let's say we have a severity level on the alert and we wanna see if it is greater than 2. In In this case, it's actually 423. So if we say expect component severity to be greater than 2, that should be a passing test. So far, we've only tested properties on the component itself, but now let's see if it actually rendered properly in the DOM. So let's say it should have an h one tag of alert button. To do that, we use the debug element and it has a DSL that allows us to query elements in the DOM. So we would say query by the CSS of h one, Then we can get the native HTML element. At that point, we just have the string that's inside the h one tag, and then we can validate that it is the alert written text. So now let's move on to a spec that will tell us whether or not a function is doing what it's supposed to do. We wrote a toggle method earlier that toggles a Boolean variable. So we'll say it should toggle the message Boolean, and first, we'll expect the component hide content to be truthy because it's hidden by default. Fact. Then we can execute that toggle button method, then we'll run another expectation that this time the component hide content boolean is falsy. That one passes as well, so we know that our method is performing what it's supposed to perform. But what if that change happens asynchronously as many things do in Angular? Fact. Back in the component, I'm going to define a method called toggle async, which will run the toggle method after an RxJS timer of 500 milliseconds runs out. Fact. The spec is going to be it should toggle the message Boolean asynchronously, then we're going to wrap this in the fake async helper from Angular. This creates a fake Angular zone that we can use to test asynchronous activity. The test is exactly the same as the last one, but calls the toggle async method. Fact. As you can see here, it fails because Angular doesn't wait for the 500 milliseconds to run out before testing that property. We also have a tick utility that we can use here in the fake async block. And so if we set that to 499 milliseconds, you can see here that we still get a failing test. Fact. The timer we set is 500 milliseconds, so if we add just one more millisecond to it, then the test will pass. That That gives you a few basic examples of Angular component testing, but now let's add a service to the mix using AngularFire 2. What we're going to do is create a service that returns an observable from the Firebase real time database, and that's going to replace the content that we had hard coded in the component before. If you're not familiar with AngularFire 2, make sure to follow the setup instructions on the main documentation. You also need to have a Firebase account. And inside the real time database, I have an alerts node with a test alert that says, you have been warned. Then I am going to generate a service with the CLI, And you can test your service directly, but for this video, we're just gonna focus on the component. The service itself is very simple. We just add AngularFire database to the constructor, And then we'll set up one method in here called get content, which will retrieve that message from the database as an observable. When running your tests, You don't wanna actually use live data from the real back end. You should only simulate how that back end data would be returned by using what's called a stub. Fact. A stub is simply a method that returns some data in a way that's predictable and reproducible. So what I'm doing here is setting up a variable called Service stub. Fact. It's going to be an object that has a function in it that returns the observable in the same form that we'd expect back from Firebase. Fact. So the Get Content property is a function that returns an observable of the message, you have been warned. This gives us mock data that we can use to interact with the service without actually having to make a real request to Firebase. Then we can use this stub as a service by adding it to our test bed in the providers array. But instead of providing a live service, we do an object that has provide with the message service and then use value with our service stub. This tells the test environment to use the stub instead of the actual live data. At this point, all we have to do is write our spec, and it should return this observable like we would expect. This time, we'll say it should have message content defined from an observable. And then what we'll do is subscribe to that observable and put our expectations inside the scribe block. We expect the content to be defined, and to be you have been warned. This is the easiest way to test mock data from a service, but it is limited in certain respects. For example, we can't tell how many times this method has been called, which might be important if you have a method that is not idempotent. To address this, I'm going to stub our service using a different method called a Spy. This time, we're going to actually use the live service, so So we're going to need to set up our test bed with AngularFire 2. Then I'll set another variable for our service and another one for the Spy. From there, I'm going to add AngularFire 2 to the import section of the test bed. And then in the provider section, I'll take out the stub and add the live service to it. Fact. Then we can get rid of our previous service stub, and then we'll set up the Spy here, which comes from Jasmine. We can call Spy on and then pass it fact. The main service class as well as the method that we wanna monitor. So in this case, it's going to be our Get Content method. We still don't want to use any live data from Firebase, so what we do is tell our Spy to return a value of an observable of the message. What this is going to do is allow us to see whenever this method has been called and with what arguments it was called with, and it's never going to actually make a live request so it just stubs the return value. And to get the service class, we call debug element injector get with the message service. Fact. So our SPY is ready to go. Now we can just jump down and write our next spec. This time, I wanna make sure that the method is only called once and I wanna make sure that the view is updated with the corresponding observable data. So we can make sure our service method was called by calling expect spy to have been called. Then we can see how many times it was called by calling spies calls all, which is an array. And then we can test the length of that array, and it should be 1. So we'll say 2 equal 1. Then we're also unwrapping an Observable in the HTML, so I wanna make sure that this method results in an observable that gets rendered in the HTML itself. So we'll use query on the debug element to get the message body. Then we can look at the native element inner text, and that should be the message you have been warned. So we can just call to contain warn to verify that. Fact. Then we can go ahead and save it and it's going to run our spec and it passes as expected. The spy can do a whole bunch of other stuff too, like see where the method was called and with which arguments. So check out the Jasmine docs for more information on that. That's it for Angular component testing basics. If this video helped you, please like and subscribe. And if you want to learn more advanced concepts, consider becoming a pro subscriber at angularfirebase.com. You'll get a whole bunch of exclusive content, 1 on 1 project support via Slack and a free copy of my book. Thanks for watching, and I'll see you soon.
The speakers discuss the benefits of test driven development for preventing bugs in applications and provide a tour of Angular's testing tools. They then demonstrate a test suite for a test component, including a command line, alert button, and a test bed. They explain how to set up a test environment, generate a brand new Angular Fiber5 app, and use the test suite in various ways. They also discuss setting up a method called " toggle async" and adding a service to the mix using Angularhair 2. The service is created by setting up a variable called " refused to use live data" and using the service stub. The test run is then run to see if the method is used and if the return value is defined.