0

I am new to the testing world, so sorry if this question is too obvious!

I have a fully functional and complex angular 9 project. I will explain my problem in simple terms here:

I have multiple services:

  1. Service_MAIN (uses HttpClient, Router, etc.)
  2. Service_A (uses Service_MAIN)
  3. Service_B (uses Service_MAIN, and etc.)

Now I have successfully tested the Service_MAIN by creating spies, etc.

  let service: Service_MAIN;

  beforeEach(() => {
    httpClientSpy = jasmine.createSpyObj('HttpClient', ['get', 'put', 'post', 'delete', 'patch']);
    routerSpy = jasmine.createSpyObj('Router', ['navigate']);

    TestBed.configureTestingModule({
      imports: [MatSnackBarModule],
      providers: [
        Service_MAIN,
        {provide: HttpClient, useValue: httpClientSpy},
        {provide: Router, useValue: routerSpy},
        SnackBarService
      ]
    });
    service= TestBed.inject(Service_MAIN);
  });

  it('should be created', () => {
    expect(service).toBeTruthy();
  });
  ...
  ...

Now when I want to test Service_A and Service_B, do I again need to create a spy for my Service_MAIN and pass httpClientspy, routerSpy, etc.?

Also, if I once create a spy for Service_MAIN in order to test Service_A, do I need to create the same spy for Service_B as well?

It would create a lot of repetition in my test files.

NOTE: Service_A does not directly use HTTPCLIENT, it uses the Service_MAIN to make HTTP calls indirectly.

Pranav Bhatia
  • 155
  • 4
  • 14

1 Answers1

0

When testing Service_A or Service_B, you can create a spyObj for Service_MAIN and mock the public methods of it that Service_A or Service_B depends on.

An example for testing Service_A.

let service: Service_A;
let mockServiceMain: any

  beforeEach(() => {
    httpClientSpy = jasmine.createSpyObj('serviceMain', [/* Put the public methods of serviceMain here as comma separated strings*/]);

    TestBed.configureTestingModule({
      imports: [],
      providers: [
        // Inject the actual service because it is to be tested
        Service_A,
        // when the service requests for Service_MAIN, use the mock value
        { provide: Service_MAIN, useValue: mockServiceMain },
        // your other providers or mock providers can go here
      ]
    });
    service = TestBed.inject(Service_A);
  });

  it('should be created', () => {
    expect(service).toBeTruthy();
  });

Also for the router, you should import RouterTestingModule and not stub it (https://angular.io/api/router/testing/RouterTestingModule). Same thing goes for HTTP, you should use HttpTestingController (https://angular.io/api/common/http/testing/HttpTestingController).

AliF50
  • 16,947
  • 1
  • 21
  • 37