FREELessons: 67Length: 8.9 hours

• Overview
• Transcript

# 8.9 Unit Testing Observables

In this lesson you'll learn a simple technique for testing observable-based code. I'll show you how to test the function which returns the observable, as well as what happens inside the success, error, and always handlers.

## 10.Conclusion1 lesson, 01:32

### 8.9 Unit Testing Observables

Hi folks, in this lesson, we're going to see how we can unit test observables in Angular. These are commonly used to handle asynchronous code, so by their very nature they are a little more complex to test than some of Angular's other constructs like services, pipes or validators. So we do have to make use of an observable in the game component to get the number fact, so let's add some tests around that. First of all, let's get the game component and the test file for the component side by side, and f describe the outer describe in the game component once again. So the observable is used in the getFact method of the game component, let's just bring that into view, And let's add a new describe in the test file, so that we can test this method. So in the getFact method we just work with the observable returned by the getNumberFact method in the gameService. So we will want to test that the getNumberFact method is called, so let's add a beforeEach that spies on this method of the game service. And let's focus just this test now first of all. We do already have a number of tests in this spec file, but really, at this point, we're only interested in the last describe that we've just added, so we can focus that as well. And let's just go to the browser and see if this first test is passing. And we can see that the test is failing, and it can't read the property subscribe of undefined. So what's happening? Well, we can see from the code on the left hand side here, we can see that after the getNumberFact method is called, the subscribe method of the return value of the getNumberFact method Is invoked straight away. So that's the subscribe that can't be called. And the reason why subscribe is trying to be called on undefined is because the getNumberFact method has been spied on and it's just returning undefined. So what we can do is have the spy return an object which contains a subscribe method. So jasmine allows us to return a value from the spy using .and.returnValue, so we can use this this to return an object that has a subscribe method. And we can use jasmine's createSpy method to create a spy, because in this case we can't use the global spyOn method. So now let's see if the test will pass now. And we can see that it does, so that's a good start. So that's okay when our testing that the getNumberFact method gets called, and that the value that it returns has a subscribe method. But what about testing what happens inside the handlers passed to the subscribe method? We can also test this code quite easily, but we'll need to capture the functions that are passed to the subscribe method. So first of all, we'll need to create some variables to store these functions in. And now inside our fake subscribe method, instead of just creating a spy, we can populate these variables. So when the test runs now, the real code will call our fake subscribe method, so the arrow function that we provided here will receive the success error and always handlers that are passed in the original code. Perfect, so now we can test what happens inside these callbacks. So let's add describes for these ones as well. So the success handler is passed a response object containing the body of the response, so we'll need to create a fake response object to pass to the handler. So this time in the, [COUGH], so this time in the arrange section, we are creating a fake response object, which has a key called body, and this key has a value of the string test. We then set a showFact property to false, and we then need to invoke the getFact method in order to stop the whole chain of calling the getNumberFact method and subscribing to the response. So now the act part of the test will need to invoke the handler, and in this case we're gonna test this successHandler. So let's see if this test is passing. And we can see that it is. So in this case, we are just asserting that the fact property of the component has been set to the string in the body of the fake response, and that the showFact property that we previously set to false has been set to true. So we can add a test in the same way for the error handler. So this time we'll need to spy on the log message of the console object. And this test will just need to test that the error message, whatever that happens to be, gets passed to the log method of the console. So this test is bit simpler, and let's see if this one is passing. And we can see that the error condition is being handled correctly, at least as far as our code is concerned. Lastly, we should also test the always handler. This one's a little trickier because it has this asynchronous set timeout inside it, but don't worry, it's still relatively trivial. We'll need a couple more imports to handle this one. So we need to bring in the tick function and the fakeAsync function from the Angular core testing module. So what does the always handler do? It sets the showFact property to false after five seconds, so that can be our test description. So this test is testing the asynchronous set timeout, so this will be an asynchronous test. And we'll need to wrap the callback passed to the it method in this fake async method as well. And that will make our test asynchronous. So this is absolutely necessary to be able to use the tick function. If we don't wrap the it in a fakeAsync zone, the test will fail and it will basically tell us to use a fakeAsync zone if we want to use tick. So inside our test then, we just need to invoke the always handler, wait five seconds and then test the showFact property. So we set the showFact property to true, and then call the getFact method to start the process off, we then call the always handler. And then we wait for five seconds, which we do using the tick function, and we pass it a number of milliseconds that we'd like to wait, and we can then make our assertion. So the test won't actually wait for five seconds, that would be crazy. And if we had lots of set timeouts all over our code, we wouldn't want to actually want to wait for the some of those to be finished running before running our tests because that could make our tests take ages. So instead a tick tricks the test runner into invoking the code straight away, so that we can test the assertion. Let's save the file and go back to the browser once more. And we can see that all three of our subscribe tests are passing. Wonderful, so in this lesson we saw how we can unit test observables in an Angular application. We saw that we can easily spy on methods that return observables, and return a fake observable that contains a subscribe method. We also saw how we can then capture the success, error, and always handlers that are passed to the subscribe method in order to test what actually happens after the request being subscribed to has occurred. Thanks for watching.

Back to the top