Error: Spy creation was anticipated to have been invoked

Currently, I am in the process of writing unit test cases for an Angular 7 Component that utilizes an async service. Unfortunately, I encountered the following error:

Error: Expected spy create to have been called once. It was called 0 times.

Below is the code snippet for my Component:

export class RegistrationComponent implements OnInit {
    
   submitRegistrationForm() {
        if (this.profileForm.invalid) {
          this.validateAllFields(this.profileForm);
        } else {
          // send a http request to save this data
          this.guestUserService.create(this.profileForm.value).subscribe(
            result => {
              if (result) {
                console.log('result', result);
                this.router.navigate(['/login']);
              }
            },
            error => {
              console.log('error', error);
            });
        }
  }

Unit test case excerpt:

  describe('RegistrationComponent', () => {
      let component: RegistrationComponent;
      let fixture: ComponentFixture<RegistrationComponent>;
      let myService;
      let mySpy;
    
      beforeEach(async(() => {
    
        TestBed.configureTestingModule({
          declarations: [RegistrationComponent],
          imports: [ ],
          providers: [
            { provide: GuestUserService, useValue: new MyServiceStub() }]
        })
          .compileComponents();
      }));
    
      beforeEach(() => {
        fixture = TestBed.createComponent(RegistrationComponent);
        component = fixture.componentInstance;
        fixture.detectChanges();
      });

 it('should submit Registration Form', async(inject([Router], (router) => {
    myService = TestBed.get(GuestUserService);
    mySpy = spyOn(myService, 'create');
    spyOn(router, 'navigate');
    spyOn(component, 'submitRegistrationForm');

component.profileForm.controls['firstName'].setValue('Arjun');
    component.profileForm.controls['lastName'].setValue('Singh');
    component.profileForm.controls['password'].setValue('12345678');
    component.profileForm.controls['confirmPassword'].setValue('12345678');
    component.submitRegistrationForm();

    expect(component.profileForm.invalid).toBe(false);

    expect(component.submitRegistrationForm).toHaveBeenCalled();

    expect(myService).toBeDefined();
    expect(mySpy).toBeDefined();
    expect(mySpy).toHaveBeenCalledTimes(1); // Receiving above error here
    expect(router.navigate).toHaveBeenCalled();
  })
  ));

Even after trying to relocate the spy declaration within beforeEach, I am still encountering the same error message. Can anyone provide guidance on how to resolve this issue?

Thank you!

Answer №1

An error is occurring because the expected spy create call has not been executed, resulting in a failed test.

This issue may arise from failing to include callThrough() on the spyOn method.

 it('should validate Registration Form submission', async(inject([Router], (router) => {

    myService = TestBed.get(GuestUserService);
    mySpy = spyOn(myService, 'create').and.callThrough(); //callThrough()

    spyOn(router, 'navigate');

    spyOn(component, 'submitRegistrationForm').and.callThrough(); //callThrough()


    component.submitRegistrationForm();

    expect(component.profileForm.invalid).toBe(false);

    expect(component.submitRegistrationForm).toHaveBeenCalled();

    expect(myService).toBeDefined();
    expect(mySpy).toBeDefined();
    expect(mySpy).toHaveBeenCalledTimes(1); 
    expect(router.navigate).toHaveBeenCalled();
  })
  ));

Answer №2

Utilizing the spyOn function allows you to set up specific reactions for when a function is called during testing, essentially creating mocks in Jasmine.

In this scenario, you have specified how the test should behave when the service function is invoked using callThrough. The key point here is that you must also take action on the service function (or the corresponding scope function) in order to activate the spyOn and execute callThrough.

it('performing snapshot loading',function(){

  //setup
  spyOn(MyService, 'loadSomething').and.callThrough(); //this is statement 2

  //act

  //either trigger the scope function utilizing the service 
  //$scope.yourServiceCallFunction();

  //or directly invoke the service function
  MyService.loadSomething(1); //this will callThrough

});

Below is a straightforward example of testing where we mimic the response of the spyOn function with a string value.

it('testing loadSomething',function(){

  //setup
  spyOn(MyService, 'loadSomething').and.returnValue('Mocked');

  //act
  var result = MyService.loadSomething(1);

  //check
  expect(result).toEqual('Mocked');
});

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Receiving time slots on a bootstrap schedule

I recently developed a calendar using Bootstrap that allows users to select a start date and automatically sets the end date within a 7-day range from the chosen start date. However, I am facing a challenge in enabling users to also pick minutes along with ...

Encountering an Issue in Angular 4 When Trying to Present JSON Data in a Table

Having trouble displaying the content of the JSON below using Angular 4 and Typescript: Display timed_out and max_score in a text box Display CV/JOB in a table. Any suggestions? { "took": 56, "timed_out": false, "_shards": { "total": 18 ...

Exploring the inner workings of view encapsulation in Angular

It is common knowledge that the default view encapsulation for a component in an Angular application is Emulated. encapsulation: ViewEncapsulation.Emulated I am quite perplexed about how it functions without being a shadow DOM. ...

Identifying the moment when attention shifts away from an element

Is it possible to detect when focus occurs outside an element without relying on global selectors like $(document), $(body), or $(window) for performance reasons? If achieving this without global selectors is not feasible, provide a provable reason expla ...

Issues with the functionality of the sliding menu in Angular are being encountered when trying to use $

Challenge I am facing an issue with a slider menu feature that I integrated into a mobile application for navigation purposes. The menu is functioning properly - it displays, allows flicking of the initial links, and can be closed by pushing the backdrop. ...

Transforming dynamic tables into JSON format

Whenever a user adds a new row to the dynamic table to input customer information, I require the data to be submitted in JSON format upon clicking the submit button. HTML <table class="table table-bordered table-hover" id="driver"> ...

Obtaining Texture Map coordinates from an Object's surface in Three.js

Seeking a solution for mapping a 3D object in Three.js to a point on its surface and finding the corresponding point on a texture file using x,y coordinates. Currently, I am using raycasting to locate points on the object's face, each of which should ...

Ways to conceal images until AFTER the completion of the jquery flexslider loading process

After trying to integrate wootheme's Flexslider on my website, I encountered a small issue with its loading process. Whenever the page is refreshed with the slider, there is a brief moment (approximately 1 second) where the first slide appears overly ...

I am experiencing issues with the Link component in Next.js version 13.4, as it

Whenever I attempt to navigate by clicking on the buttons labeled About, Experience, and others, the page does not redirect me accordingly. Oddly enough, if I manually input the endpoint for that specific page like http://localhost:3000/#about, it function ...

Restore Bootstrap Dropdown values to their initial settings when clicked

I need a button that can reset all filter dropdown values to their default values. The current code I have only changes all values to "Filter" when reset, but I specifically need it to reset to "Car brand" and "Model". Here's my code: // set.... $(" ...

The Express API is failing to recognize the data keys that were sent from the React frontend, despite being clearly specified

I am facing an issue while trying to send data to a REST API using React hosted in a separate application. The API does not seem to receive the keys sent, even though I checked the results in Chrome and found this output:(2) ["imageSrc", File]0: "imageSrc" ...

What is preventing me from directly assigning properties to my data object?

Struggling to access my question props in order to assign its property directly into my data properties. Although I can use the property directly from my template, I am unable to assign it into the data. Currently, I can only retrieve the value of props f ...

Run the *.js file only when the current month is December

Alright, I'm stumped. I've been trying to create this script: <script> $(document).ready(function(){ var d = new Date(); n = d.getMonth(); if (n == 11) { src="extrafiles/effect/snow.js"; } }); </script& ...

Crafting dynamic parameters in the Express router - A step-by-step guide!

Original Code Example: const express = require('express'); const router = express.Router(); router.get('/data/:d1/:d2/:d3', require('../apifoo').foo); Route: /data/:d1/:d2/:d3 Path: /data/1/2/3 req.params : 'd1' : ...

What is the reason for the jQuery callBack handler returning [object Object]?

Recently, I created a SessionMgr.cfc file in ColdFusion to manage session variables for my $.ajax calls. However, it seems like I might have made a mistake somewhere. Despite scouring through numerous pages on Stack Overflow and Google, I still can't ...

How to sort objects by keys in AngularJS

Currently, I am working on building a sorting list using AngularJS. The goal is to have the data updated in the DOM dynamically when a user clicks on the name of a value. I am attempting to order the values by categories such as Bracelets, Charms, Earrings ...

Is there a way to manually add route resolve data to a controller without using automatic injection?

Two routes in my application share a controller, but one route requires data to be resolved before the view loads while the other does not. Here is an example of the routing segments: ... when('/users', { controller: 'UsersCtrl', ...

What causes the variance in timestamps between JavaScript and PHP?

I am facing a discrepancy between the JavaScript and PHP timestamps I have created. There is roughly a 170-second difference between the two. 1302162686 PHP - time() 1302162517 JavaScript - Math.round(new Date().getTime() / 1000) If anyone has any insi ...

Is it possible to optimize the performance of my React and TypeScript project with the help of webpack?

I am working on a massive project that takes 6 to 8 minutes to load when I run npm start. Is there a way to speed up the loading process by first displaying the sign-in page and then loading everything else? ...

Implementing authentication using JWT in .NET Core and Angular 7: A comprehensive guide

The startup file for .NET Core 2.2 has been configured as shown below: var key = Encoding.ASCII.GetBytes(AppSettings.Secret); services.AddAuthentication(x => { x.DefaultAuthenticateScheme = IISDefaults.AuthenticationScheme; ...