TL;DR Mock your service.

Explanation

In your testbed, you provide the actual service :

providers:[ServiceProvidersHTTPService, ...

This means you actually call the real methods of your service.

If you mock your service, like you did there :

{provide: AppConfigService, useClass: MockAppConfigService }

Then you call random functions that you declare in your mock.

Another advantage of mocking, you get rid of the dependencies of your dependencies.

As you said, your service calls another service : if you mock your first service, you don't have to add the dependencies of this service into your testbed.

So, they way to go :

const mock = {
  provide: ServiceProvidersHTTPService,
  useValue: {
    getAllUsers: () => null
  }
};

In your testbed now :

providers: [mock, ...

In useValue, you must put all the variables and all the functions of your actual service, and mock them.

In this case, instead of making HTTP calls, your function getAllUsers will simply return null. You can make it return anything you want (the good practice is to return a value that is the same type of the value that should be returned).

Last piece of advice : your unit tests should test only the functions and methods of your actual feature (here being ProjectAnalystComponent). You should not test if your service call the other service here : you should test that in the unit testing of your service.

If you have any questions, feel free to ask !

Answer from user4676340 on Stack Overflow
🌐
Gitbook
duncanhunter.gitbook.io › testing-angular › test-the-component-logic-using-spyon
9. Test the Component logic using SpyOn | Testing Angular
import { of } from 'rxjs'; import { AppComponent } from './app.component'; import { AppService } from './app.service'; import { Name } from './app.models'; describe(`Component: App Component`, () => { let appService: AppService; let component: AppComponent; beforeEach(() => { appService = { getNames: () => of([]) }; component = new AppComponent(appService); }); it('add 1+1 - PASS', () => { expect(1 + 1).toEqual(2); }); it(`title equals 'testing'`, () => { expect(component.title).toEqual('testing'); }); it(`Expect service to return a single name`, () => { component.ngOnInit(); component.names$.
🌐
DigitalOcean
digitalocean.com › community › tutorials › angular-testing-with-spies
How To Use Spies in Angular Testing | DigitalOcean
June 21, 2021 - Here’s how you’d use Jasmine’s spyOn function to call a service method and test that it was called: ... import { TestBed, waitForAsync, ComponentFixture } from '@angular/core/testing'; import { By } from '@angular/platform-browser'; import { DebugElement } from '@angular/core'; import { AppComponent } from './app.component'; import { IncrementDecrementService } from './increment-decrement.service'; describe('AppComponent', () => { let fixture: ComponentFixture<AppComponent>; let debugElement: DebugElement; let incrementDecrementService: IncrementDecrementService;
🌐
CodeCraft
codecraft.tv › courses › angular › unit-testing › mocks-and-spies
Testing with Mocks & Spies • Angular - Courses
/* tslint:disable:no-unused-variable */ import { LoginComponent } from './login.component'; import { AuthService } from "./auth.service"; describe('Component: Login', () => { let component: LoginComponent; let service: AuthService; let spy: any; beforeEach(() => { service = new AuthService(); component = new LoginComponent(service); }); afterEach(() => { service = null; component = null; }); it('needsLogin returns true when the user has not been authenticated', () => { spy = spyOn(service, 'isAuthenticated').and.returnValue(false); expect(component.needsLogin()).toBeTruthy(); expect(service.isAuthenticated).toHaveBeenCalled(); }); it('needsLogin returns false when the user has been authenticated', () => { spy = spyOn(service, 'isAuthenticated').and.returnValue(true); expect(component.needsLogin()).toBeFalsy(); expect(service.isAuthenticated).toHaveBeenCalled(); }); });
🌐
GitHub
github.com › angular › angular › issues › 8947
Provide spyOn to angular testing class · Issue #8947 · angular/angular
June 1, 2016 - import { describe, beforeEach, it, expect, spyOn } from '@angular/core/testing'; spyOn(thing, 'method');
Author   krimple
🌐
YouTube
youtube.com › codehandbook
Angular Unit Testing : Using spyOn to Mock and Stub Methods | Karma | Jasmine | With Source Code - YouTube
#spyOn #mock #stub #karma #jasmineHow to use spyOn in Angular unit testing ?In this video, you'll learn how to use spyOn to spy over methods. Using spyOn you...
Published   May 28, 2021
Views   29K
🌐
Medium
frontendinterviewquestions.medium.com › how-does-spyon-work-in-angular-4087f3b2919d
How does spyOn work in Angular ?. Source:- How does spyOn work in Angular | by Pravin M | Medium
April 13, 2024 - import { Injectable } from '@angular/core'; @Injectable() export class DataService { fetchData(): Promise { return new Promise((resolve) => { // Simulating an asynchronous API call setTimeout(() => { const data = 'Some data from API'; resolve(data); }, 1000); }); } } Now, let’s write a unit test for the `DataService` using `spyOn` to mock the API call:
🌐
Codehandbook
codehandbook.org › home › mock service using spy on angular unit testing karma jasmine
Mock Service Using SpyOn | Angular Unit Testing | Karma | Jasmine -
June 21, 2021 - How to use spyOn in Angular Unit Testing? How to mock a service in Angular Unit Testing ? Here is your component code that you want to unit test. import { Component } from '@angular/core'; import { DataServiceService } from '../app/data-service.service'; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css'] }) export class AppComponent { title = 'angu-unit-test'; constructor(private dataService : DataServiceService){} count = 0; config = {}; data; calculate(a,b){ this.count = (a * b) + 100 return this.
Find elsewhere
🌐
Testing-angular
testing-angular.com › faking-dependencies
Faking dependencies (Mocking) – Testing Angular
February 17, 2021 - // Fake todos and response object const todos = [ 'shop groceries', 'mow the lawn', 'take the cat to the vet' ]; const okResponse = new Response(JSON.stringify(todos), { status: 200, statusText: 'OK', }); describe('TodoService', () => { it('gets the to-dos', async () => { // Arrange spyOn(window, 'fetch') .and.returnValue(okResponse); const todoService = new TodoService(); // Act const actualTodos = await todoService.getTodos(); // Assert expect(actualTodos).toEqual(todos); expect(window.fetch).toHaveBeenCalledWith('/todos'); }); });
🌐
ScriptVerse
scriptverse.academy › tutorials › jasmine-spyon.html
Jasmine Spies: The spyOn() Function
In Sinon, a spy calls through the method it is spying on. So, sinon.spy(s,'nextSeason'); in Sinon is equivalent to spyOn(s,'nextSeason').and.callThrough(); in Jasmine.
Top answer
1 of 4
28

I take a slightly different approach and use inject itself to get hold of the service instance through DI instead. So your test would look like:

import {
  describe, 
  expect, 
  it,
  tick,
  inject,
  fakeAsync,
  TestComponentBuilder,
  ComponentFixture,
  addProviders
} from 'angular2/testing';

import { Component, provide } from '@angular/core';

import {UserListComponent} from './user-list.component';

import {UserService} from './user.service';
import {MockUserService} from './user.service.mock';

describe('When loading the UserListComponent', () => {

  beforeEach(() => addProviders([
      {provide: UserService, useClass: MockUserService}
  ]));

  it('should call the getAllUsers method from the UserService', 
    inject([TestComponentBuilder, UserService], fakeAsync((tcb: TestComponentBuilder, mockUserService: UserService) => {
      spyOn(mockUserService, 'getAllUsers');

      tcb
        .createAsync(UserListComponent)
        .then((fixture: ComponentFixture) => {
          tick();
          fixture.detectChanges();
          expect(mockUserService.getAllUsers).toHaveBeenCalled();
        });
    }))
  );

  it('should show one mocked user', 
    inject([TestComponentBuilder, UserService], fakeAsync((tcb: TestComponentBuilder, mockUserService: UserService) => {
      mockUserService.setResponse([{
        username: 'ryan',
        email: '[email protected]'
      }]);

      tcb
        .createAsync(UserListComponent)
        .then((fixture: ComponentFixture) => {
          tick();
          fixture.detectChanges();
          let compiled = fixture.debugElement.nativeElement;
          expect(compiled.querySelector('div:nth-child(1) .username')).toHaveText('Username: ryan');
          expect(compiled.querySelector('div:nth-child(1) .email')).toHaveText('Email: [email protected]');
        });
    }))
  );

});

Edit for Angular 4

The latest docs have a simpler way of getting hold of a service using the component's injector:

  fixture = TestBed.createComponent(TestComponent);
  component = fixture.componentInstance;
  const mockService = fixture.debugElement.injector.get(MyService);

Edit for Angular 5+

  import { Component, Injector, Type } from '@angular/core';
  ...

  fixture = TestBed.createComponent(TestComponent);
  component = fixture.componentInstance;
  const mockService = fixture.debugElement.injector.get<MyService>(MyService as Type<MyService>);
2 of 4
9

The other solutions didn't work for me so I injected the service with injector from debugElement.

import { TestBed, 
         async }  from '@angular/core/testing';

@injectable()
class MyService {
  public method () {}
}

let MyMockedService = {
  method: () => {}
}

@Component({
  template: ''
})
class MyComponent {
  constructor(private myService: MyService) {;}
  public method () {
    this.myService.method();
  }
}

describe('Test', () => {
  beforeEach(async(() => {
    TestBed
      .configureTestingModule({
        imports: [
          CommonModule
        ],
        declarations: [
          MyComponent
        ],
          providers: [
            { provide: MyService, useValue: MyMockedService}
        ]
      })
      .compileComponents()
      .then(() => {
        fixture = TestBed.createComponent(MyComponent);
        myComponent = fixture.componentInstance;
      });
  }));
  it('should spy on service', () => {
    let myMockedService = fixture.debugElement.injector.get(MyMockedService);
    spyOn(myMockedService, 'method');
    myComponent.method();
    expect(myMockedService.method);
  });
})
🌐
Medium
shashankvivek-7.medium.com › testing-a-component-with-stub-services-and-spies-in-jasmine-1428d4242a49
Testing Angular Components with Stub Services and Spies in Jasmine | by Shashank Vivek | Medium
August 28, 2020 - We can override a function behavior using “spyOn” and can return custom value using .and.returnValue(). throwError comes from RxJS and provide error response which can be imported as · import { throwError } from 'rxjs'; Here are the complete unit tests which we have written in my GitHub repository. Cheers !! JavaScript · Angular ·
🌐
Inoaspect
inoaspect.com.au › home › typescript › angular unit testing – spyon – eventemitter
Angular Unit testing – spyOn – EventEmitter | INOASPECT
September 9, 2021 - it('should emit "next" with parameter "Active" when onChange is called with "Active"', () => { const spy = spyOn(component.onItemSelect, 'next'); component.onChange('Active'); expect(spy).toHaveBeenCalledWith('Active'); }); November 18, 2020 ...
🌐
DanyWalls
danywalls.com › how-and-when-to-use-mocks-or-spies-on-unit-testing
How and When to Use Mocks or Spies on Unit Testing | DanyWalls
December 30, 2022 - In this example, we use the spyOn function to create a spy for the exportInvoiceLibrary and spy the method called sendToGovernment, which we have not configured to do anything in particular.
🌐
Plunker
embed.plnkr.co › HBhNwn
Angular Example - Testing - Jasmine spy on static method - Plunker
Use of this source code is governed by an MIT-style license that can be found in the LICENSE file at http://angular.io/license */ import { Endpoint } from './endpoint'; describe("when constructing end point class", function() { let endpoint; beforeEach(function() { spyOn(Endpoint, "prefill") endpoint = new Endpoint("typeA", 3); }) it("calls prefill", function() { expect(Endpoint.prefill).toHaveBeenCalledWith("typeA", 5); }) });