Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to test map and tap pipe from RXJS in Angular

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.

enter image description here

like image 921
ineedtoknow Avatar asked Sep 02 '25 04:09

ineedtoknow


1 Answers

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.

like image 182
AliF50 Avatar answered Sep 05 '25 01:09

AliF50