Simulating an API endpoint using a spy service (using Jasmine)

I'm currently trying to simulate an API route within a spy service using Jasmine.

Being relatively new to Angular, Typescript, and Jasmine, I find myself uncertain about where to place my code - whether it should go in the beforeEach block or in its own it('should do xyz...') block, and so on.

I presume that I should execute the mock setup within the beforeEach, but I'm encountering an issue with the payload (details below).

spec.ts:

providers: [
   { provide: MyService, useValue: CommonServiceSpies.createHttpClientSpy()},
]

beforeEach(() => {
    fixture = TestBed.createComponent(ManagerComponent);

    const myVar = TestBed.inject(MyService) as jasmine.SpyObj<MyService>;
    
    const payload = 123 // I had an object similar to the one from component.ts file, but it doesn't work with the current service setup // The error message received was: "Account of type Observable<{}> is not assignable to param of type 'Observable<number>'"

    myVar.GetRemainingAmount.and.returnValue(of(payload)); // Error thrown says: "cannot read property 'and' of undefined"

    fixture.detectChanges();
});

it('should create', () => {
    expect(component).toBeTruthy();
});

service.ts:

export class MyService {
    constructor(
        private http: HttpClient
    ) { }

    GetRemainingAmount(request: RemainingAmountRequest): Observable<number> {
        return this.http.post<number>('/some-route', request);
    }

manager-component.ts:

constructor(
    public myService: MyService
  ) { } 

 hasRemainingSpend() : void {
    const payload: RemainingAmountRequest = {
      accountId: this.account.id,
      otherId: this.xyz?.id
    }

    this.myService.GetRemainingAmount(payload).subscribe((response: number) => {
      this.warningSpend = response;

      if (this.warningSpend < this.rate.value || this.warningSpend == null) {
        // call another func
        // this is working as expected
      }
    })

  }

Answer №1

I'm unsure of the exact functionality of

CommonServiceSpies.createHttpClientSpy()
, but my assumption is that it creates an HTTP spy.

For more information on Angular unit testing and mocking external dependencies, check out this resource.

In order to mock a service in Angular unit testing, you can follow these steps:

// Define a variable for the spy object outside beforeEach
let mockMyService: jasmine.SpyObj<MyService>;
// Inside the TestBed.configureTestingModule beforeEach block,
// create the spy object with methods to be mocked
mockMyService = jasmine.createSpyObj<MyService>('MyService', ['GetRemainingAmount']);
providers: [
   // Provide the created spy object
   { provide: MyService, useValue: mockMyService},
]

beforeEach(() => {
    fixture = TestBed.createComponent(ManagerComponent);
    // Return an empty response for the method
    myService.GetRemainingAmount.and.returnValue(of({}));
   
    fixture.detectChanges();
});

it('should create', () => {
    expect(component).toBeTruthy();
});

If you prefer not to create a mock object, you can update your existing code as follows:

Replace this line:

myVar.GetRemainingAmount.and.returnValue(of(payload));

With:

spyOn(myVar, 'GetRemainingAmount').and.returnValue(of({}));

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

Attempting to create a login feature using phpMyAdmin in Ionic framework

Currently, I am in the process of developing a login feature for my mobile application using Ionic. I am facing some difficulties with sending data from Ionic to PHP and I can't seem to figure out what the issue is. This is how the HTML form looks li ...

What causes the map function to behave differently when I use an array as the return value rather than a primitive in the callback function?

Program var corporations=[ {name:'Vicky',category:'Devdas',start:1993,end:2090}, {name:'Vikrant',category:'Devdas',start:1994,end:2019}, {name:'Akriti',category:'mental',start:1991,end:2021}, { ...

Angular 4, Trouble: Unable to resolve parameters for StateObservable: (?)

I've been working on writing unit tests for one of my services but keep encountering an error: "Can't resolve all parameters for StateObservable: (?)". As a result, my test is failing. Can someone please help me identify and fix the issue? Here& ...

Ways to fake an interface using Jest without needing to instantiate it

While Kotlin supports this, I haven't been able to find a way to achieve the same in Jest. My problem arises from having intricate interfaces and arrays of these interfaces where specifying all attribute values is not ideal. Here's an example of ...

The absence of a 'defaultValue' argument in Typescript React is causing an issue

I'm encountering an issue with my code. The error message states "An argument for 'defaultValue' was not provided." I am trying to set default values but unsure of what those values should be. Additionally, I am facing a couple of other err ...

Modeling a potentially empty array in Typescript can be achieved by implementing specific interface definitions

Here is the current situation: type A = { b: string, c: number } I have an object that I will receive from an API, which could be either A[] or [] As of now, when I attempt to use it, const apiData: A[] || [] const b = apiData[0].a // I expected this to ...

Resetting the Angular2 poller in an ng-bootstrap accordion

I am currently utilizing a multi-dimensional array connected to a reactive poller that waits for a database state update. Interestingly, when I initially load the state once, the user interface functions as intended. However, a challenge arises when I act ...

Filtering JSON array data in Typescript can help streamline and optimize data

Recently diving into Angular, I am facing a challenge with filtering data from a JSON array. My goal is to display names of items whose id is less than 100. The code snippet below, however, is not producing the desired result. list : any; getOptionList(){ ...

Security concern regarding XSRF in Spring and Angular 5

For my current project, I am using Spring as the backend (generated with microservices with Jhipster) and Angular5 as the frontend. On the server side, CSRF security is added (it was enabled by default when we created microservices with Jhipster). Workin ...

Transform object into data transfer object

Looking for the most efficient method to convert a NestJS entity object to a DTO. Assuming the following setup: import { IsString, IsNumber, IsBoolean } from 'class-validator'; import { Exclude } from 'class-transformer'; export clas ...

Refining a collection of item elements by examining a string attribute, disregarding letter case differences

I'm working on a code snippet that generates item components from my list of objects (Frivillig). <app-frivillig-item *ngFor="let frivilligEl of frivillige" [frivillig]="frivilligEl"> </app-frivillig-item> Now, I have a new requireme ...

Troubleshooting the issue with mocking the useTranslation function for i18n in JEST

Currently, I am facing an issue with my react component that utilizes translations from i18next. Despite trying to create tests for it using JEST, nothing seems to be getting translated. I attempted to mock the useTranslation function as shown below: cons ...

Encountering TS2304 error message while running TypeScript files indicates the inability to locate the name 'PropertyKey', in addition to another error - TS2339

I encountered an issue while attempting to execute a spec.ts file in the Jasmine Framework. After installing @types/core-js version 0.9.46 using the command npm i @types/core-js, I started receiving the following error messages: > ../../node_modules/ ...

The argument represented by 'T' does not align with the parameter represented by 'number' and therefore cannot be assigned

I am confused as to why, in my situation, <T> is considered a number but cannot be assigned to a parameter of type number. Changing the type of n to either number or any resolves the issue. Error: Code: const dropFoo = <T>(arr: T[], n: T): T ...

Error: When running the NPM CI command in a GitHub action, the package nice-napi is not accessible from

I've recently set up a Github action to build and run tests on every pull request. However, the action suddenly stopped working even though no changes were made to the code base. Here is the current code for the action: name: Test pull request on: ...

What is the best way to implement multiple HTTP subscriptions in a loop using Angular?

I find myself in a predicament where I need to iterate through an array of strings passed as parameters to a service, which then responds through the HTTP subscribe method. After that, some operations are performed on the response. The issue arises when t ...

Is there a surefire method to ensure that ChromeDriver in Protractor consistently uses the stable version?

Every time Chrome releases an update, I encounter a recurring issue. Allow me to paint the picture: All browsers are at version 83 of Chrome Chrome announces that version 84 is on its way, but it has not been released yet. A new ChromeDriver 84 is rolled ...

How to implement ngx-infinite-scroll in Angular 4 by making a vertically scrollable table

Looking for a way to make just the table body scrollable in Angular 4 using ngx-infinite-scroll. I've tried some CSS solutions but haven't found one that works. Any help or documentation on this issue would be greatly appreciated. I attempted th ...

Implementing Service Communication

I created an Angular Application using the Visual Studio Template. The structure of the application is as follows: /Clientapp ./app/app.module.shared.ts ./app/app.module.client.ts ./app/app.module.server.ts ./components/* ./services/person-data.service. ...

Having issues with ngbDropdown in Angular 4 from ng-bootstrap?

My dropdown menus are malfunctioning. I attempted to follow advice from this source, where I upgraded to bootstrap 4-alpha, but unfortunately, the issue persists. Here is an excerpt from my package.json file: "@angular/animations": "^4.3.0", ... // ...