I am wanting to test my code below, but I'm not sure how to test the map and tap (from RXJS) functions. Should I make a mock, use a spy?
Should I even really test these? I have a habit of getting 100% coverage for only achieving that goal (100% coverage), but I'm learning that 100% isn't always needed or beneficial. But in this case, map and tap are pretty crucial to the function. I'd really appreciate any advice, thank you.
I am using Angular 9.
The red lines are untested.
Yes, getting 100% coverage probably is not the best idea but is a good goal to shoot for.
As I see your service does HTTP requests, follow this guide for the testing: https://medium.com/better-programming/testing-http-requests-in-angular-with-httpclienttestingmodule-3880ceac74cf.
And yes, you will have to mock loggingService
;
Something like this:
import { TestBed } from '@angular/core/testing';
import { CoursesService } from './courses.service';
import { HttpClientTestingModule,
HttpTestingController } from '@angular/common/http/testing';
... // the rest of your imports
describe('TemplateService', () => {
// We declare the variables that we'll use for the Test Controller and for our Service
let httpTestingController: HttpTestingController;
let service: TemplateService;
let mockLoggingService: any;
beforeEach(() => {
// 'loggingService' is for your own sanity and the array are all of the public methods of `loggingService`
mockLoggingService = jasmine.createSpyObj('loggingService', ['logger']);
TestBed.configureTestingModule({
providers: [
TemplateService,
// every time the test asks for LoggingService, supply this mock
{ provide: LoggingService, useValue: mockLoggingService },
],
imports: [HttpClientTestingModule]
});
// We inject our service (which imports the HttpClient) and the Test Controller
httpTestingController = TestBed.get(HttpTestingController);
service = TestBed.get(TemplateService);
});
afterEach(() => {
httpTestingController.verify();
});
// Angular default test added when you generate a service using the CLI
it('should be created', () => {
expect(service).toBeTruthy();
});
it('should make a get call for getTemplates and log', () => {
const mockTemplates: Template[] = [/* you know how a template should look like so mock it*/];
// make HTTP call take flight
service.getTemplates().subscribe(templates => {
expect(templates).toEqual(mockTemplates);
expect(mockLoggingService.logger).toHaveBeenCalledWith(`User viewed templates: ${templates}`);
});
// have a handle on the HTTP call that is about to take flight
const req = httpTestingController.expectOne(/* put the unique url of this method's get request that only you know of */);
expect(req.request.method).toEqual('GET');
// send this request for the next HTTP call
req.flush(mockTemplates);
});
it('should make a get call for getTemplateById and log', () => {
const mockTemplate: Template = {/* you know how a template should look like so mock it*/};
// make HTTP call take flight
service.getTemplateById(1).subscribe(template => {
expect(template).toEqual(mockTemplate);
expect(mockLoggingService.logger).toHaveBeenCalledWith(`User viewed template: ${template}`);
});
// have a handle on the HTTP call that is about to take flight
const req = httpTestingController.expectOne(/* put the unique url of this method's get request that only you know of */);
expect(req.request.method).toEqual('GET');
// send this request for the next HTTP call
req.flush(mockTemplates);
});
});
Side Note: Your maps
are doing nothing in both functions and they can be removed. They are just returning what they are receiving and are not transforming anything.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With