What are the best methods for testing Angular functions that utilize the http.get function?

After completing the Angular tour of heroes, I delved into writing tests for it. While some tests were straightforward to write, I encountered difficulties when attempting to fetch data from the server. Despite researching topics like testing controllers, defers, marbles, and schedulers, I find myself at a standstill with no clear direction on how to proceed. The outcome either results in persistent test failures or passing tests with 'SPEC HAS NO EXPECTATIONS', which essentially equates to an empty test.

//Test
it('#updateHero() works', waitForAsync(inject([HeroService], (service: HeroService) => {
let testHero = {
  id: 42,
  name: 'TestHero'
} as Hero
service.updateHero(testHero).subscribe()
service.getHero(42).subscribe(hero => expect(hero.name).toBe('TestHero'))
})));
//service
getHero(id: number): Observable<Hero> {
const url = `${this.heroesUrl}/${id}`
return this.http.get<Hero>(url).pipe(
  tap(_ => this.messageService.add(`fetched hero id=${id}`)),
  catchError(this.handleError<Hero>(`getHero id=${id}`)))}


updateHero(hero: Hero): Observable<any> {
return this.http.put(this.heroesUrl, hero, this.httpOptions).pipe(
  tap(_ => this.messageService.add(`updated hero id=${hero.id}`)),
  catchError(this.handleError<any>('updateHero'))
)}

In several other tests, I faced the same challenge where my services failed to retrieve any data despite the application itself functioning flawlessly.

My colleagues provided little help in addressing my concerns, offering unconventional suggestions like mocking the entire server response instead.

Answer №1

After experimenting with various methods, I finally devised the solution outlined below:

...
beforeEach(async () => {
let router = {
  snapshot: {
    paramMap: {
      get: () => 1, // representing the bookId
    },
  },
};

await TestBed.configureTestingModule({
  declarations: [ DetailComponent ],
  imports: [ HttpClientTestingModule ],
  providers: [
    {
      provide: ActivatedRoute,
      useValue: router
    },
  ],
})
.compileComponents();

...
});

it('Testing http.get hero functionality', () => {
const heroes: Hero[] = [
  { id: 1, name: 'Fake Batman1', imgSrc: '../assets/Batman.jpg', score: -5, commentary: 'FAKE!!!!!' },
  { id: 2, name: 'Fake Batman2', imgSrc: '../assets/Batman.jpg', score: -5, commentary: 'FAKE!!!!!' },
  { id: 3, name: 'Cool Batman', imgSrc: '../assets/Batman.jpg', score: 20, commentary: 'The coolest batman ever' },
  { id: 4, name: 'Fake Batman3', imgSrc: '../assets/Batman.jpg', score: -5, commentary: 'FAKE!!!!!' },
  { id: 5, name: 'Batman', imgSrc: '../assets/Batman.jpg', score: 3, commentary: 'No opinion' },
  { id: 6, name: 'Fake Batman4', imgSrc: '../assets/Batman.jpg', score: -5, commentary: 'FAKE!!!!!' },
]
const req = httpTestingController.expectOne('api/heroes/1');
expect(req.request.method).toEqual('GET');
req.flush(heroes[2]);
httpTestingController.verify();
});

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

Error Message: Unexpected character "C" found in JSON response from Ionic 2 Http GET request

Trying to execute a GET request and extract data from the response. this.http.get('http://localhost:8888/maneappback/more-items.php').subscribe(res => { console.log(res.json()); }, (err) => { console.log(err); }); An error message ...

Using Typescript alongside Angular 1.6 and browserify for your development needs

Currently navigating the world of working with Angular types in TypeScript and bundling code using Browserify. After following a TypeScript guide related to Gulp, I utilized npm to install the Angular types and put together this simple ts file. import * a ...

Converting axios response containing an array of arrays into a TypeScript interface

When working with an API, I encountered a response in the following format: [ [ 1636765200000, 254.46, 248.07, 254.78, 248.05, 2074.9316693 ], [ 1636761600000, 251.14, 254.29, 255.73, 251.14, 5965.53873045 ], [ 1636758000000, 251.25, 251.15, 252.97, ...

Steps for Automating Updates to a Kanban List in Real-Time Following the Creation of a New Task Using MongoDB

'm currently developing a Kanban app and facing an issue with updating the task list immediately after adding a new task. I'm utilizing MongoDB alongside Express and Axios, but struggling to refresh the list dynamically without a full page reload ...

Resharper griping about TypeScript object in Angular 2

Currently, I have Resharper 10 integrated into Visual Studio 2015. https://i.stack.imgur.com/vksGb.png In the screenshot, highlighted by the green box, there's an issue with valid decorator syntax which results in this error message: Cannot conve ...

Dealing with circular references in class attributes within Angular

I'm facing a challenge in Angular while trying to set up mock data. I have the following two classes: export class Company { public id: number; public name: string; public applications: Application[]; constructor(id: number, name: string, ap ...

Removing a key from an index signature in Typescript - a step-by-step guide

In my web application built with Angular, we encountered a need for a data type to store translations of strings in different languages. To address this requirement, a team member defined the following type: export class TranslatedString { [language: str ...

Navigating with additional parameters using ? and & symbols

I've been struggling to understand how Angular's routing system works, but so far I haven't been successful. My goal is to extract all the parameters from a URL using Angular's route functionality. Let's consider this example URL: ...

The issue with session storage persisting even after closing the iframe

Encountering a persistent issue where the sessionStorage remains populated even after closing an iframe and opening another one with the same destination. I assumed that the sessionStorage would be reset and start afresh each time. The iframe is contained ...

The type '{ domain: any; domainDispatch: React.Dispatch<any>; }' cannot be assigned to a type 'string'

Within my codebase, I am encountering an issue with a small file structured as follows: import React, { createContext, useContext, useReducer } from 'react' const initState = '' const DomainContext = createContext(initState) export co ...

Synchronize Angular 5's provision of injection tokens

Is there a way to delay the provision of an InjectionToken until a previous provider's useFactory is finished? For instance, I would like to set MyInjectionToken only after the APP_INITIALIZER token has been allocated. providers: [ HttpClient, MySer ...

Encountering a warning during the installation of Angular CLI

As a newcomer to this platform, I recently installed Node.js. However, when attempting to execute the command npm install -g @angular/cli, an error was encountered: **npm WARN deprecated [email protected]: Legacy versions of mkdirp are no longer supported ...

Webpack encountering issues with loading dependencies within dependencies

When I try to run webpack, it seems that the compiler is having trouble loading my app.module from within main.ts. Without using webpack, my application can find all modules correctly, but with Webpack, it's failing. This is my webpack configuration: ...

Exploring the usage of array map parameters in rxjs 6 when combined with withLatestFrom

Prior to Rxjs 6, we were able to achieve the following: interface TypeA { payload: any; } source$.pipe( withLatestFrom(source2$, (source1: TypeA, source2: TypeB) => ({ payload: source1.payload, source2 }) ), ) In the resultSelector method ...

Error: { "message": "sqlite3_prepare_v2 error: token "876EL003" not recognized", "code": 5}

I am having trouble filtering the SQLite data with two conditions. I keep getting an unrecognized token error and I suspect that my query statement might be incorrect in the script. Could you please take a look and see if you can help me out? Thank you! ...

Converting a string to a number is not functioning as expected

I am facing a problem with an input shown below. The issue arises when trying to convert the budget numeric property into thousands separators (for example, 1,000). <ion-input [ngModel]="project.budget | thousandsSeparatorPipe" (ngModelChange)="projec ...

Angular is getting hung up on the process of "reloading client(s)" and failing to properly refresh the page

As a React developer, I've decided to start learning Angular. I created a new project using "ng new my-first-app", but I'm facing an issue with hot module reload. It stops working shortly after I make changes to the "app-component.html" file and ...

An object may be null when its type is A or undefined, but we are certain it is not undefined

Since the release of version 4.8.4, the TypeScript compiler has been flagging an issue with the following code: type A = {v: number} function get_the_first<T>(xs: T[]): T | undefined { if (xs.length > 1) return xs[0]; else ...

Implementation of a nested interface using a generic and union types

I am seeking to create a custom type that will enable me to specify a property for a react component: type CustomType<T> = { base: T; tablet?: T; desktop?: T; }; export type ResponsiveCustomValue<T> = CustomType<T> | T; This ...

What is the process of branching a stream with highland.js?

I have a stream called sourceStream that contains objects of type BaseData. My goal is to split this stream into n different streams, each filtering and transforming the BaseData objects according to their specific criteria. Ultimately, I want to end up ...