Testing a service is not much more difficult than testing a filter, in fact, the same rules applies. The difficulty comes on what you do with your service. It is not the same thing testing a service that holds data (a wizard for example) than a service that does RESTful stuff + cache. I plan to write more testing examples on the future but for this article we are going to set the basics :)
So what are we going to do on this service? Well taking advantage of my toastr library, I thought about a logger service. What can we do with it? Let me think… Right, we could use it to log to the dev console using its
error functions and also optionally pop up a toast with proper colors to match those functions. Sounds good to me, let’s go:
1 2 3 4 5 6 7 8
Well, we created a variable to hold our
logger service and also one to hold the
toastr service. Then we injected the logger and saved it. What should we do with the
This is a common pain point for new users. I bet that the half of you would have this question here: How can I test that the toast is on the screen? The answer is: You don’t care. This is a UNIT test, that means that you’re testing that concrete unit and you shouldn’t care about its dependencies. If it is another service you made, you would have tests for it and if it is a third party dependency, it has its own tests (or it should :P). So in this case, the
toastr service is already tested so you don’t have to care.
Alright, having that in mind, the common path here is to spy the functions we are going to use from the
toastr service and also the functions from the console. I am going to show you two different ways:
The previous code would end like this:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
For the console, we are going to stick on
spyOn from jasmine as we did on a previous article, but for
toastr we did something completely new. We replaced the
toastr service with one we made right here, in other words, a complete mock.
Basically, when we loaded the
app module (we do this on the
app module because it is where the service is created or added as a dependency) we created a new
toastr object and then we created 3 spies (more on this shortly). After that we just needed to create a new
value service that will create/override the
If we have a service (of any kind) with a certain name and we after that create another service (of any kind) with that same name, it will be overriden. That is whycreating a simple
valueservice will override the previous one.
If we load the original
toastrlibrary on the test, it will be overriden but in this case, we can just ignore the dependency and a new
toastrservice will be created. In any case we have what we need.
What about those
createSpy? They do more or less the same as
spyOn. What’s the difference?
spyOn is used to spy an existing function and
createSpy will create a dummy spied function. Since our new
toastr service has none, we can create spied functions from scratch, handy.
Alright, our preparations are done, let’s write a couple of tests:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
Here we are testing the different combinations of our
logger. As you can see, it has 3 parameters, one for the message, one for the log type and one boolean for our
toastr popup. The type parameter is optional and will use
log by default. Also I provided a fallback option to the library.
The final result of the service is:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
I mapped the console functions to the toastr function that has the most appropiated colors. And the log function is easy, we just log and show a popup if needed.
Even when we used a
factory here, testing a
service is not different.
You can see it live here.