{"id":1094,"date":"2023-06-22T05:00:00","date_gmt":"2023-06-22T12:00:00","guid":{"rendered":"https:\/\/www.angulartraining.com\/daily-newsletter\/?p=1094"},"modified":"2023-06-21T16:02:19","modified_gmt":"2023-06-21T23:02:19","slug":"how-to-unit-test-an-angular-service","status":"publish","type":"post","link":"https:\/\/www.angulartraining.com\/daily-newsletter\/how-to-unit-test-an-angular-service\/","title":{"rendered":"How to unit test an Angular service?"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">Yesterday, we covered <a href=\"https:\/\/blog.angulartraining.com\/how-to-unit-test-an-angular-pipe-eb5cacb018cc\" target=\"_blank\" rel=\"noopener\" title=\"\">how to unit test an Angular pipe<\/a>. Services are a bit more complex to test because they usually have dependencies that need to be injected. Let&#8217;s consider this example:<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full is-resized\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/www.angulartraining.com\/daily-newsletter\/wp-content\/uploads\/2023\/06\/image-22.png\" alt=\"\" class=\"wp-image-1095\" width=\"634\" height=\"438\" srcset=\"https:\/\/www.angulartraining.com\/daily-newsletter\/wp-content\/uploads\/2023\/06\/image-22.png 766w, https:\/\/www.angulartraining.com\/daily-newsletter\/wp-content\/uploads\/2023\/06\/image-22-300x207.png 300w\" sizes=\"auto, (max-width: 634px) 100vw, 634px\" \/><\/figure>\n<\/div>\n\n\n<p class=\"wp-block-paragraph\"><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">All the service does is rely on the <code>HttpClient<\/code> to make requests to a server. In a unit test, we don&#8217;t want to have a server up and running for the test to work. Instead, we want to focus on <code>CartService<\/code> only and replace all its dependencies with fake implementations called <strong>mocks<\/strong>.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Replacing a dependency with a mock requires some dependency injection config, which is why the setup of a service test is different. Here is what Angular CLI generates for us automatically:<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"420\" height=\"322\" src=\"https:\/\/www.angulartraining.com\/daily-newsletter\/wp-content\/uploads\/2023\/06\/image-23.png\" alt=\"\" class=\"wp-image-1096\" srcset=\"https:\/\/www.angulartraining.com\/daily-newsletter\/wp-content\/uploads\/2023\/06\/image-23.png 420w, https:\/\/www.angulartraining.com\/daily-newsletter\/wp-content\/uploads\/2023\/06\/image-23-300x230.png 300w\" sizes=\"auto, (max-width: 420px) 100vw, 420px\" \/><\/figure>\n<\/div>\n\n\n<p class=\"wp-block-paragraph\"><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">We can see that the test relies on a <code><a href=\"https:\/\/angular.io\/api\/core\/testing\/TestBed\" target=\"_blank\" rel=\"noopener\" title=\"\">TestBed<\/a><\/code> object to create a testing module and then inject <code>CartService<\/code> in our test. <code>TestBed<\/code> is an Angular utility that enables custom dependency injection in unit tests. We are going to use <code>TestBed<\/code> to replace our real <code>HttpClient<\/code> with a fake one.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The simplest fake implementation we can create to satisfy our unit test is the following:<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full is-resized\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/www.angulartraining.com\/daily-newsletter\/wp-content\/uploads\/2023\/06\/image-24.png\" alt=\"\" class=\"wp-image-1097\" width=\"267\" height=\"151\"\/><\/figure>\n<\/div>\n\n\n<p class=\"wp-block-paragraph\"><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The above mock object has hardcoded methods that return the same Observables for each HTTP request. The next step is to configure our <code>TestBed<\/code> so our test uses that mock instead of the real <code>HttpClient<\/code>:<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full is-resized\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/www.angulartraining.com\/daily-newsletter\/wp-content\/uploads\/2023\/06\/image-25.png\" alt=\"\" class=\"wp-image-1098\" width=\"603\" height=\"89\" srcset=\"https:\/\/www.angulartraining.com\/daily-newsletter\/wp-content\/uploads\/2023\/06\/image-25.png 577w, https:\/\/www.angulartraining.com\/daily-newsletter\/wp-content\/uploads\/2023\/06\/image-25-300x44.png 300w\" sizes=\"auto, (max-width: 603px) 100vw, 603px\" \/><\/figure>\n<\/div>\n\n\n<p class=\"wp-block-paragraph\"><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">At this point, our test setup is ready. We can start writing actual test cases. We want to test <code>getCartContents<\/code> and make sure that it returns an empty array. The challenge at that point is that our method returns an Observable, which means we have to subscribe to it and then test the result:<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"498\" height=\"138\" src=\"https:\/\/www.angulartraining.com\/daily-newsletter\/wp-content\/uploads\/2023\/06\/image-26.png\" alt=\"\" class=\"wp-image-1099\" srcset=\"https:\/\/www.angulartraining.com\/daily-newsletter\/wp-content\/uploads\/2023\/06\/image-26.png 498w, https:\/\/www.angulartraining.com\/daily-newsletter\/wp-content\/uploads\/2023\/06\/image-26-300x83.png 300w\" sizes=\"auto, (max-width: 498px) 100vw, 498px\" \/><\/figure>\n<\/div>\n\n\n<p class=\"wp-block-paragraph\"><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The above test works! We got the Observable from our mock and checked the empty array. The test passes. That said, when working with Observables, it is recommended to use the <code>async<\/code> function as follows to make sure that the test waits long enough before completing:<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"529\" height=\"164\" src=\"https:\/\/www.angulartraining.com\/daily-newsletter\/wp-content\/uploads\/2023\/06\/image-27.png\" alt=\"\" class=\"wp-image-1100\" srcset=\"https:\/\/www.angulartraining.com\/daily-newsletter\/wp-content\/uploads\/2023\/06\/image-27.png 529w, https:\/\/www.angulartraining.com\/daily-newsletter\/wp-content\/uploads\/2023\/06\/image-27-300x93.png 300w\" sizes=\"auto, (max-width: 529px) 100vw, 529px\" \/><\/figure>\n<\/div>\n\n\n<p class=\"wp-block-paragraph\"><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Note that <code>async<\/code> has to be passed as a parameter to the test function (first line of code) and then called as the last line in our subscribe callback function.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">There are other approaches to testing services that rely on the HttpClient. This one is the most straightforward, but if you&#8217;re interested, I have another<a href=\"https:\/\/blog.angulartraining.com\/how-to-write-unit-tests-for-angular-code-that-uses-the-httpclient-429fa782eb15\" target=\"_blank\" rel=\"noopener\" title=\"\"> tutorial that uses the official Angular mock API for the <code>HttpClient<\/code><\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Yesterday, we covered how to unit test an Angular pipe. Services are a bit more complex to test because they usually have dependencies that need to be injected. Let&#8217;s consider this example: All the service does is rely on the HttpClient to make requests to a server. In a unit test, we don&#8217;t want to [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[4,19],"tags":[],"class_list":["post-1094","post","type-post","status-publish","format-standard","hentry","category-angular","category-testing"],"aioseo_notices":[],"_links":{"self":[{"href":"https:\/\/www.angulartraining.com\/daily-newsletter\/wp-json\/wp\/v2\/posts\/1094","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.angulartraining.com\/daily-newsletter\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.angulartraining.com\/daily-newsletter\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.angulartraining.com\/daily-newsletter\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.angulartraining.com\/daily-newsletter\/wp-json\/wp\/v2\/comments?post=1094"}],"version-history":[{"count":2,"href":"https:\/\/www.angulartraining.com\/daily-newsletter\/wp-json\/wp\/v2\/posts\/1094\/revisions"}],"predecessor-version":[{"id":1102,"href":"https:\/\/www.angulartraining.com\/daily-newsletter\/wp-json\/wp\/v2\/posts\/1094\/revisions\/1102"}],"wp:attachment":[{"href":"https:\/\/www.angulartraining.com\/daily-newsletter\/wp-json\/wp\/v2\/media?parent=1094"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.angulartraining.com\/daily-newsletter\/wp-json\/wp\/v2\/categories?post=1094"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.angulartraining.com\/daily-newsletter\/wp-json\/wp\/v2\/tags?post=1094"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}