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

How to efficiently eliminate multiple entries with SREM in ioredis?

I am curious about the proper syntax for removing multiple entries using the SREM command. When I try this: const myKey = "myKey"; const entriesToRemove: string[] = ... this.redisClient.srem(myKey, entriesToRemove); I end up with: ReplyError: ...

Problem displaying images in Mean stack app using CSS background-image and Webpack

Currently, I am enhancing my skills by working on my own projects. One of the projects I'm focused on right now is designing a MEAN-stack app that utilizes Webpack. In the past, I encountered an issue where I couldn't display images in my app. Ho ...

Conditional types can be used as type guards

I have this simplified code snippet: export type CustomType<T> = T extends Array<unknown> ? {data: T} : T; function checkAndCast<T extends Array<unknown>>(value: CustomType<T>): value is {data: T} { return "data" ...

Primeng - Concealed dropdown values within a scrollable table header

Recently, I integrated Primeng p-table with a filter and frozen column feature (with one column being fixed while the others are movable). However, I encountered an issue with the select dropdown in the header. When I try to open the dropdown, the values a ...

Collaborate and reuse Typescript code across various Node projects

Imagine we have a project structured like this: webapps ProjectA SomeClass.ts Package.json ProjectB SomeClass.ts Package.json Common LoggingClass.ts Package.json The Common "LoggingClass" needs to import a module from NPM. Let's say that ...

How can I retrieve the current table instance in NGX-Datatables?

I have a component that includes a table. This table receives RowData from another component through the use of @Input. How can I access the current instance of this table? Here is a snippet of my HTML: <ngx-datatable class="material" ...

Transmitting image data (blob) from the frontend to the backend using Next.js and tRPC (T3 stack)

I'm currently facing a challenge in sending a leaflet map image from the backend to the frontend using the leaflet-simple-map-screenshoter library for capturing the image. The library returns a blob, which I need to transmit back to the backend and sa ...

Expanding external type declarations within Typescript

I am currently working with Typescript and the ant design library. My goal is to extend an existing interface by adding a single property. To start, I imported the original interface so you can see the folder structure: import { CollapseProps } from &apo ...

Angular 4 with Typescript allows for the quick and easy deletion of multiple selected rows

I am currently working on an application where I need to create a function that will delete the selected checkboxes from an array. I have managed to log the number of checkboxes that are selected, but I am struggling to retrieve the index numbers of these ...

A step-by-step guide to customizing the Material UI Chips delete SVG icon to appear in white color through

Using a Material UI component, I added a custom class to my chip. Attached is a screenshot showing what I mean. Currently, I am attempting to change the color of the cross button to white. After inspecting the element, I discovered that it is an SVG ico ...

transformation of categorized unions in software development

Experimenting with routing-controllers and its built-in class-transformer feature, I tried creating an interface for executing a search query based on either a location id or location coordinate. My aim was to utilize a discriminated union as a body parame ...

Typescript: When using ts-node-dev, an error occurred while trying to import express due to an unexpected

I am embarking on a fresh project using Typescript and I intend to set up the node server with typescript utilizing express. There's a helpful tutorial that explains how to execute a Typescript file without going through the hassle of compiling files, ...

Implementing Immer in Typescript

Recently, I've been exploring the possibility of integrating Immer into my React project that already utilizes Typescript. Unfortunately, I haven't been able to discover a clear guide on how to effectively employ Immer in conjunction with Typescr ...

Learn the steps to establish a one-to-many relational record with the help of Node.js and Sequelize-Typescript

Currently, I am working on Nodejs with sequelize-typescript to develop a CRUD system for a one-to-many relationship. Unfortunately, I have encountered an issue with my code that I cannot seem to pinpoint. While I am able to retrieve records successfully us ...

Utilizing Angular HTTP Interceptor to Show Loading Spinner Across Multiple Modules

My goal is to utilize the ng4-loading-spinner spinner when making HTTP calls to my API. I referred to the examples provided in the following resources: Angular Guide on Intercepting HTTP Requests/Responses Stack Overflow Post on Using HttpClient Interce ...

How do I incorporate global typings when adding type definitions to an npm module?

Suppose I create a node module called m. Later on, I decide to enhance it with Typescript typings. Luckily, the module only exports a single function, so the m.d.ts file is as follows: /// <reference path="./typings/globals/node/index.d.ts" /> decl ...

Having trouble with importing a TypeScript class: encountering a "cannot resolve" error message

Could you lend me your expertise? I'm puzzled by this issue that seems to be quite simple and straightforward: export class Rectangle { height: number = 0 width: number = 0 constructor(height: number, width: number) { this. ...

What is the best way to make the current tab stand out?

I have implemented a TabHeader component to create a dynamic Tab Menu that displays table contents based on months. The loop runs from the current month back to January, and the content is updated dynamically through an API call triggered by changes in the ...

Running PM2 with Angular-CLI is a great way to ensure your Angular2 project runs smoothly and efficiently

Is there a way to run ng serve --prod with pm2 on DigitalOcean for an Angular 2 project? I attempted to use http-server -p 4200 -d false in the dist/ folder after running ng build --prod, but when I try to access the website , I encounter a 404 error (eve ...

There was an issue converting the value {null} to the data type 'System.Int32', resulting in a 400 error

Attempting to make a POST request with some missing data is causing errors in my angular form. Here is the payload I am using: DeviceDetail{ deviceId:'332', sideId: null, deviceName:'test' } Unfortunately, I encountered a 400 bad re ...