From the course: Angular: Testing and Debugging

Testing services - Angular Tutorial

From the course: Angular: Testing and Debugging

Start my 1-month free trial

Testing services

- Let's add a basic unit test called a spec for our user list service to confirm that it returns an array of 16 users. The Angular CLI tool created a spec file for us. When we generated the UserListService. Angular wants to make our lives easier. So it already imported TestBed and our UserListService class. It also makes a simple passing test right here. This is a great starting point for real-world projects but for this video, let's pretend we're starting from scratch without Angular's help. I'm going to delete the content of this file so we can build our tests manually. Select all. Delete. The first thing we do is import our UserListService class. I'll make a new import statement and type import, UserListService from ./user-list.service. Angular comes with the Jasmine testing framework and all Jasmine tests happen inside a describe block like this. describe() is a global function introduced by Jasmine. So there's nothing to import here. This function expects two arguments. The first argument is a string used to describe the collection of tests we're going to run inside this block. You can call your spec suite, whatever you'd like. I'll call mine UserListSurface. The second argument is a callback function that holds all of our tests. Inside this callback, I'll create a new property in our callback function to represent an instance of the service we want to test. I'll make a new line and type let service: UserListService Notice that I use the let keyword here instead of const. This is on purpose. Normally it's a good idea to create read only variables using the const keyword. But in this case we need to instantiate a new instance of our service each time we run a test. We do this using Jasmine's beforeEach function. Jasmine runs this function Once before every test that follows in the describe block. It looks like this: This function takes a call back as its first argument. In the callback, I'll set the value of our service property to a new instance of the UserListService, so far so good. But, we don't have any tests yet. For that, we need to use Jasmine's It function. We use this function to declare the actual test logic as well as any test specific setup for the code. The It function takes two arguments. The first is a string to label a test. You can call your test, whatever you'd like I'm going to label mine as should return a User List with 16 users. The second argument is a callback function with all of our test logic and setup code. Angular is asynchronous by design, but Jasmine is not. So we need to tell Jasmine when all the asynchronous work is finished. There are a few ways to do this. But, the simplest way is to use Jasmine's done function. I'll pass in done as the first argument of our callback and I'll set its type as the DoneFn interface. DoneFn is also a global. So, nothing to import here either. By default, Jasmine waits five seconds for asynchronous tests to finish. If a test doesn't finish in time, it's marked as failed, and Jasmine continues with the rest of the test suite. You can pass in an optional third argument to the it function to set a timeout value to something other than five seconds. This timeout value is in milliseconds. So I would pass in 10,000 for 10 seconds, 2000 for two seconds, and so on. The default time will be good enough for our use case here. In the callback for our test, we use our service the same way we would in real app code. I'll move to the inside callback and I'll type service.getAll(). All the test logic happens inside the callback of the then method. I'll pass in the response from getAll like this and I'll make a new line. And I'll hand off this response to Jasmine's test logic using the expect and toBe functions. Expect always takes in the value we're testing. In this case, it's going to be response.length, and the toBe method takes in the value we must see to pass the test. In this case, the integer 16. The toBe function is one of many Jasmine functions we can use to test our code. I recommend reviewing the official Jasmine documentation for a deeper look at all your testing options. The last thing we need to do is call the done function to tell Jasmine, to run our test. I'll make a new line and type done(). That's it. We made our first unit test. We use the Angular CLI tool to run our unit tests. I'll open a new terminal window here in VS Code and type npm run test. I could call the ng test command directly, but I like using the npm script to make sure I'm using the locally installed version of ng. Instead of the globally installed version on my machine. When I hit the enter key, Angular will compile our code, launch an instance of Google Chrome, and run our tests. Let's do that now. And, here are our results. Okay. It looks like we have two failures; One in the web storage service, and the other in the user list component. Now there's a lot of data here in these error messages, but it's mostly a stack trace. The important info is at the top where it says: NullInjectorError: No provider for HTTPClient. We'll take a look at how to fix these errors in the next video.

Contents