You need to set up the spy before the method is called. Jasmine spys wrap function to determine when they are called and what they get called with. The method must be wrapped before the spied on method is called in order to capture the information. Try changing your test to match the following:

it('should foobar', () => {
    spyOn(component, 'bar');
    component.foo();
    expect(component.bar).toHaveBeenCalled();
})
Answer from Teddy Sterne on Stack Overflow
🌐
GitHub
github.com › cypress-io › cypress › discussions › 26081
[Documentation - Angular] What is the best practice for spying on component methods? · cypress-io/cypress · Discussion #26081
From the comments it would appear this things like this are not the goal of cypress component testing. At this point I would see it as feature incomplete and I don’t understand why. Beta Was this translation helpful? Give feedback. ... There was an error while loading. Please reload this page. Something went wrong. There was an error while loading. Please reload this page. ... Yes you can. You would just need to inject the service see an example here. And then you can use cy.spy() to spy on the method(s) you want to validate
Author   cypress-io
Discussions

[Documentation]: Interaction tests: how to spy on component methods - or is it not permitted?
Example: the component is an Angular component and has an input called myInput and a public method called myMethod. ... From the docs, anything passed to args is automatically converted to a spy. More on github.com
🌐 github.com
10
August 12, 2023
unit testing - How to spy a service call in Angular2 - Stack Overflow
Following the code example found on Ari Lerner ng-book2, and using Angular 2 beta 7, I'm trying to mock and spy a call to a service unsuccessfully. This is the main component using the service: u... More on stackoverflow.com
🌐 stackoverflow.com
How to spyOn child components in Angular? - Stack Overflow
I don't know how to tell HeroesListComponent to use the mock object when i'm inside heroes.component.spec.ts ... I had a stubbed child component where I wanted to confirm that certain functions on it were being called per my component's logic. More on stackoverflow.com
🌐 stackoverflow.com
July 27, 2017
unit testing - Angular test - set up a spy on a function of the SUT component before the component is created by TestBed - Stack Overflow
I have an Angular component I am writing tests for. The SUT component has a function I need to spy on (not ideal as noted further below). I want to set up the TestBed so that the function already h... More on stackoverflow.com
🌐 stackoverflow.com
🌐
DigitalOcean
digitalocean.com › community › tutorials › angular-testing-with-spies
How To Use Spies in Angular Testing | DigitalOcean
June 21, 2021 - Jasmine spies are used to tracking or stub functions or methods. Spies are an easy way to check if a function was called or to provide a custom return value. We can use spies to test components that depend on a service and avoid actually calling the service’s methods to get a value.
🌐
Gitbook
duncanhunter.gitbook.io › testing-angular › test-the-component-logic-using-spyon
9. Test the Component logic using SpyOn | Testing Angular
SpyOn is a Jasmine feature that allows dynamically intercepting the calls to a function and change its result. This example shows how spyOn works, even if we are still mocking up our service.
🌐
Medium
luardo.medium.com › testing-with-mocks-spies-using-createspyobj-in-angular-1e31bf7f6147
Testing with Mocks & Spies using createSpyObj in Angular | by Luis Eduardo | Medium
February 26, 2021 - That feels like too much boilerplate if you have many services injected into your component. There is a simpler way to mock services by creating a Spy Object. A Spy is a feature of Jasmine that allows you to stub any function and track calls to it back. It’s usually used to mock a function or an object. But let’s not confuse a spy with a spyObj. jasmine.createSpy: can be used when there is no function to spy on. jasmine.createSpyObj: it’s used to create mocks that will spy on methods.
🌐
GitHub
github.com › storybookjs › storybook › issues › 23821
[Documentation]: Interaction tests: how to spy on component methods - or is it not permitted? · Issue #23821 · storybookjs/storybook
August 12, 2023 - Example: the component is an Angular component and has an input called myInput and a public method called myMethod. ... From the docs, anything passed to args is automatically converted to a spy.
Author   CMadden8
🌐
Testing-angular
testing-angular.com › faking-dependencies
Faking dependencies (Mocking) – Testing Angular
February 17, 2021 - When the code under test changes, the test may accidentally call original methods of the dependency. This guide will present thorough faking techniques that do not allow a slip. They imitate the original code while shielding the original from calls. Jasmine provides simple yet powerful patterns to create fake implementations. The most basic pattern is the Jasmine spy for replacing a function dependency.
Find elsewhere
🌐
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 - Testing component by isolating it from external dependencies such as services and using : ... 2. Getting to know spies and how it can prove to be a helpful tool for Unit Testing. We’ll be using below spies whose details can be found on Jasmine page :
🌐
CodeCraft
codecraft.tv › courses › angular › unit-testing › mocks-and-spies
Testing with Mocks & Spies • Angular - Courses
We do this by creating Mocks; we can create Mocks using fake classes, extending existing classes or by using real instances of classes but taking control of them with Spies. Listing 3. login.component.ts · import {Component} from '@angular/core'; ...
🌐
Simple Web Learning
simpleweblearning.com › simple web learning › working with spies in angular unit test
Working with Spies in Angular Unit Test | Simple Web Learning
August 21, 2021 - Spy is a feature in Jasmine that allows you to spy on something to achieve the following goals: Monitor if a function is called along with the parameters pass to it · Override function return values or properties to simulate desired situations ...
🌐
Angular.love
angular.love › create-your-angular-unit-test-spies-automagically
Create your Angular unit test spies automagically
Read the prototype properties, it's where the methods get attached to in javascript, and for each method instantiate a jasmine Spy! There is one small issue here and that is if the dependency we are mocking has properties autoSpy would slap & jasmine.Spy on them too, which would later make it harder to assign values to.
🌐
ConcretePage
concretepage.com › angular › angular-test-spy-method
Angular Test Spy on Method
May 4, 2022 - Find the technologies being used in our example. 1. Angular 13.1.0 2. Node.js 12.20.0 3. Jasmine 3.10 4. Karma 6.3 · The Jasmine createSpyObj creates an object with multiple spies as its members. createSpyObj(baseName, methodNames, propertyNamesopt) baseName : We can pass class name as base name.
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);
  });
})
Top answer
1 of 3
4
  1. As I have used providers in the Profile Component, can I inject the Profileervice in the profile.component.spec.ts file as it will create two instance of the same service..??

Answer: You should create a Stub for the service to replace dependency on actual ProfileService using useClass

export class ProfileServiceStub {
    getData(id: string) {
       return of({some_obj: "value"})
    }
}

and in spec.ts

    beforeEach(async(() => {
        TestBed.configureTestingModule({
            imports: [HttpClientTestingModule, ReactiveFormsModule, RouterTestingModule],
            declarations: [ProfileComponent],
            providers: [ {provide: ProfileService , useClass: ProfileServiceStub } ], // <-- useclass here
            schemas: [NO_ERRORS_SCHEMA]
        }).compileComponents();
  1. How to spy on login() and getData() of ProfileService as below statement is not working...?

Answer: Make the service public in component constructor as below:

constructor(public profileService: ProfileService) { }

I would strongly recommend you to read my article on something similar where I have tested the component

2 of 3
0

1.) I think what you have is fine, putting ProfileService in the provider array in TestBed.configureTestingModule is good and when the component gets created, it knows how to make it. Each time the component gets created, it will be a separate provider but this will be the case whether providing the provider in the component or globally since a test constructs and destructs (beforeEach.... TestBed.configureTestingModule....).

2.) Try `spyOn(profileService, 'login').and.returnValue(Promise.resolve({}));

Side note: The ngOnInit needs an async decorator in order to use await.

🌐
Angular
angular.dev › guide › testing › components-scenarios
Component testing scenarios • Angular
The related HeroDetail component tests will assert that methods of the HeroDetailService were called by spying on the service methods.