Unit testing an Angular 2+ service that makes an httpclient get request through another service

While there are numerous resources available online for testing a service that sends an API request, I am facing challenges in testing a service that:

  • invokes another service that sends an HTTP request and then returns the response to the original service
  • sends an HTTP request based on the above scenario

Below is a snippet of my code where I'm encountering difficulties:

beforeEach((done) => {
    TestBed.configureTestingModule({
        imports: [
            RouterTestingModule,
            HttpClientTestingModule,
            JwtModule.forRoot({
                jwtOptionsProvider: {
                    provide: JWT_OPTIONS,
                    useFactory: jwtOptionsFactory,
                    deps: []
                }
            }),
        ],
        providers: [
            ConfigService,
            AuthenticationService,
            UserService,
            JobService
        ]
    });

    let injector = getTestBed();
    sut = injector.get(JobService);
    httpMock = injector.get(HttpTestingController);
});

describe('Appointment Management', () =>{
    it('should set an appointment', () => {
        expect(sut).toBeDefined();
        const dummyResponse = 'dsfsdf';

        sut
        .setAppointmentDate('temp', new Date(2017, 12, 31))
        .subscribe(result => {
            expect(result).toEqual(dummyResponse)
        })

        const req = httpMock.expectOne('http://localhost:32307/appointments');
        expect(req.request.method).toBe('POST');
        req.flush(dummyResponse);
    });
})

To provide further context, the job service is the main focus of this test, with dependencies on configService and userService.

The user service relies on configService and authentication service, while router and jwt service are essential for authentication service and user service.

All services also require the use of HttpClient.

THE ERROR MESSAGE I AM ENCOUNTERING:

Error: Timeout - Async callback was not invoked within timeout specified by jasmine.DEFAULT_TIMEOUT_INTERVAL.

Even though there should be no actual external calls made during testing, I am puzzled as to why it times out. I attempted stubbing out the dependency calls, but it resulted in the same error, similar to:

const userRequest = httpMock.expectOne('http://localhost:32307/user');
userRequest.flush('temp');

Answer №1

When conducting unit tests, the focus is on verifying the functionality of the service being tested. Testing the behavior of its dependencies is not required.

Essentially, you need to ensure that the service correctly invokes other services and then simulate their responses using mocking.

If jobService is the target of the test and it interacts with config & user services (based on your explanation), the testing approach should be as follows:

US = injector.get(UserService);
CS = injector.get(ConfigService);

it('Testing a function named myFunc in your service...', () => {
  spyOn(US, 'myUserServiceFunctionCalled')
    .and.returnValue(Observable.of('The mocked response from this function'))
  spyOn(CS, 'myConfigServiceFunctionCalled')
    .and.returnValue(Observable.of('The mocked response from this function'))

  sut.myFunc(); // Call .subscribe if the result is an Observable, and include your assertions inside
  expect(US.myUserServiceFunctionCalled).toHaveBeenCalled();
  expect(CS.myConfigServiceFunctionCalled).toHaveBeenCalled();
});

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

Using ngFor to connect input with the Algolia Places feature

I have implemented an Algolia Places input within an ngFor loop using Angular8. The issue I am facing is that the (change) event only works properly after typing in the input for the second time. While this is functional, it's not exactly the behavior ...

Scrolling Container Following Down the Page, Halts at Its Own Bottom (Similar to Twitter)

I am facing an issue and need some help. I am working on creating a three-column page layout where the middle section is for posts, the right section is for links and references (a bit long), and the left section is fixed. My question is: How can I preven ...

Error encountered in Nest.js tests due to dependency injection issues between modules. The module 'src/foo/foo.module' cannot be located from 'bar/bar.service.spec.ts'

Encountering an error message Cannot find module 'src/foo/foo.module' from 'bar/bar.service.spec.ts' while testing a service that relies on another module. I am facing difficulty in setting up the test scenario for a Nest.js project wi ...

Update the directive automatically whenever a change occurs in the root scope property

I am facing an issue with a directive that generates a random number. My goal is to reload or refresh this directive when a checkbox is toggled. Below is the code I have been using, but unfortunately, it's not working as expected. var app = angular. ...

Vue.js numerical input module

My approach involves utilizing Numeral.js: Vue.filter('formatNumber', function (value) { return numeral(value).format('0,0.[000]') }) Vue.component('input-number', { templa ...

Is there a method to measure the time it takes to download a script apart from its actual execution time

I am looking to track timing variables for my primary JavaScript load. One approach could be: <script> performance.mark('script-start') </script> <script src="something.js"></script> Later in something.js, inc ...

Utilizing OrbitControls with SVGRenderer displays a pair of SVG elements positioned at opposite ends

In my project, I have created two scenes and two renderers. One scene is for a simple 3D mesh sphere, while the other is for an SVG circle. The SVG scene is positioned on top of the Mesh scene, acting as an overlay. Both the sphere and the circle are place ...

implementing jqBarGraph on my webpage

Hey there! I have been trying to add a graph to my HTML page for quite some time now. After doing some research, I discovered that using the jqBarGraph plug-in makes it easier to create the desired graph. Below you will find the code that I have on my webp ...

Access scope information when clicking with ng-click

I am currently using a php api to update my database, but I want the ability to choose which item gets updated with ng-click. app.controller('ReviewProductsController', function ($scope, $http) { $scope.hide_product = function () { ...

Safari is encountering a 'Invalid Date' error in Javascript

Help me solve this issue with my script: var date = new Date("19871104071535".replace( /^(\d{4})(\d\d)(\d\d)(\d\d)(\d\d)(\d\d)$/, '$4:$5:$6 $2/$3/$1' )); alert(date); The script run ...

Exhibition of items arranged in a floating manner. I am looking to insert a new class within the layout using jquery

Let's dive into a bit more detail. I have a gallery with 9 elements aligned to the left, creating 3 elements per line as shown below: 1 2 3 <--line 1 4 5 6 <--line 2 7 8 9 <--line 3 What I am attempting to do is wh ...

Exploring the power of jQuery and Ajax together

Today seems to be one of those days where even the simplest tasks become a challenge. I'm sorry if this question has been asked before, but I'm struggling with a basic issue. I want to dynamically update text on a website using a text file, and w ...

To prevent a JavaScript or jQuery method from affecting an anchor tag, assign a specific value to its href attribute

I have a jQuery function that triggers an action when an anchor tag is clicked. Now, I am looking for a way to prevent the button from being responsive to jQuery on subsequent clicks. Any suggestions? Currently, my approach involves changing the innerHTML ...

JS roles encountered an issue with a TypeError: it is unable to read the property 'push' because it is undefined

I'm experiencing a problem with setting roles in the admin panel of my website. The roles I've configured are mmUser, mmMerchant, mmAdmin. When a user signs up, they are automatically assigned the mmUser role. In the admin panel, I'm attemp ...

The issue with 'DemoCtrl' defined in Angular JS is that it does not correspond to a valid argument

signup.html <div ng-controller="UniqueCtrl" layout="column" ng-cloak="" class="md-inline-form inputdemoBasicUsage" ng-app="inputBasicDemo"> <md-content md-theme="docs-dark" layout-gt-sm="row" layout-padding=""> <div> <md- ...

Adding input fields that change dynamically along with their corresponding radio buttons using AngularJS

Hello, I am struggling with implementing a feature in my HTML and AngularJS files (using Bootstrap ui). I want to create a new input field (td) along with three corresponding radio buttons when the user clicks on an add button. I have attempted to modify t ...

Using Javascript to automatically replace content when the page is loaded

Having trouble with my fullCalendar jquery calendar and the 'eventClick' method. When I click on an event, the URL is getting encoded incorrectly. For example, I'm trying to pass a Wordpress URL like this: http://sitedomain.com/?post_type= ...

Preserving the true IP address when initiating cross-domain requests

Initially, I tried creating a reverse proxy using Express to enable forwarding requests from localhost:3000/request to somesite.com/request. Here is the code snippet I used: var request = require('request'); app.get('/', function(req, ...

How can I incorporate a spinning cog from Font Awesome into a jQuery click event?

I am looking to incorporate a spinning font awesome cog while the data is being fetched and remove it once the process is complete. Here is the HTML snippet that needs to be inserted: <i class="fa fa-spin fa-cog"></i> And this is the accompa ...

Activate a click event on an element using Simple HTML DOM

I need assistance in triggering a click on the element below and then retrieving its innertext. <a class="btn btn-sm btn-default" href="javascript:;" onClick="score(238953,this)">Show result</a> Once the "onClick" event is triggered, the elem ...