Search code examples
angularjasminekarma-jasmineangular-test

Angular Jasmine spy not being called


I'm following the official Angular tutorial to test a component that calls an asynchronous service function: https://angular.io/guide/testing#component-with-async-service

Creating the spy:

const gardenSpy = jasmine.createSpyObj('GardenService', ['getGardens', 'createGarden']);
gardenSpy.getGardens.and.returnValue(of(testGardens));
...
gardenServiceSpy = TestBed.get(GardenService);

Configuring the TestBed to use my spy instead of the actual service:

TestBed.configureTestingModule({
  declarations: [ MyGardensComponent ],
  providers: [
    { provide: GardenService, useValue: gardenSpy }
  ],
  imports: [FormsModule, HttpClientTestingModule]
})
.compileComponents();

Then, the unit test that is failing:

it('should load the gardens', () => {
  fixture.detectChanges();
  component.getGardens();

  expect(gardenServiceSpy.getGardens.calls.any()).toBe(true, 'getGardens called');
});

As you can see by the coverage report here, the subscribe method is never executed, and the spy assertion fails.

coverage report

According to the Angular tutorial, this method should work and allow me to return the observable synchronously. Calling the spy method manually works and returns correctly, so I assume there is an issue with the injection of the spy service, rather than the creation of the spy itself. Any help would be appreciated!

If you need to see the whole files, I made a plunker here (doesn't actually run, just to see the files)


Solution

  • Thanks for providing all your code in the Plunker. I actually moved it to a Stackblitz so I could see exactly what you are seeing and watch it run. I had to stub the service, but that is pretty irrelevant since you are replacing it with a spy anyway.

    I got it working by commenting out the providers line in your my-gardens.component.ts file in the @Component section:

    @Component({
      selector: 'app-my-gardens',
      templateUrl: './my-gardens.component.html',
      styleUrls: ['./my-gardens.component.css'],
      // providers: [GardenService, NgbModal]
    })
    

    This was effectively overriding the spy with the original service. Was there a reason you put the providers line in there rather than in the module.ts?

    As you can see in the Stackblitz, the test is now passing and the subscribe code is being called (check the console log).