AngularJS, Promise in Jasmine test fails to resolve

My tests are failing because I can't get my promise to resolve. Within my application, I have two essential services:

1- The first service is called ServerApiService and it is responsible for making calls to the server:

angular.module('test').service('serverApiService', ['$http', function($http) {
    var self = this;

    self.generateRequest = function(actionName, data) {
        console.log('request generated');
        //Normally returns 'return $http(config);'
    };

}]);

2- The second service depends on ServerApiService and it manages solutions, named SolutionService:

angular.module('test').service('solutionService', ['$q', 'serverApiService', function($q, serverApiService) {
    var self = this;

    self.list = function(account) {
        var data = {
          id: account.id
        };

        var deferred = $q.defer();

        serverApiService.generateRequest('solutions.list', data).then(function(response) {
            var solutions = [];

            for(var i = 0; i < response.Items.length; i++) {
                var solutionJSON = response.Items[i];
                var studyJSON = solutionJSON.Study;

                var solution = {};
                solution.id = solutionJSON.Id;

                var study = {};
                study.name = studyJSON.Name;


                solution.study = study;
                solutions.push(solution);
            }

            deferred.resolve(solutions);
        });

        return deferred.promise;
    };

}]);

Troubleshooting

I am trying to test the SolutionService module by creating a mock of the ServerApiService, however, I am struggling to get the spy function to return the promise. Here is the relevant test code snippet:

describe('solution service', function () {

    var mockServerApiService, solutionSvc;

    beforeEach(function() {
        module('test');
    });

    beforeEach(function() {
        module(function($provide) {
            $provide.service('serverApiService', function($q) {
                this.generateRequest = jasmine.createSpy('generateRequest').and.callFake(function(actionName, data) {
                    var deferred = $q.defer();

                    deferred.resolve({Items: [
                      {
                        Id: '910759',
                        Study: {
                          Id: '213123',
                          Name: 'test'
                        },
                      },
                      {
                        Id: '4406510',
                        Study: {
                          Id: '063294',
                          Name: 'test2'
                        },
                      }, 
                      ]});

                    return deferred.promise;
                });
            });
        });

    });



    beforeEach(inject(function (serverApiService, solutionService) {
        mockServerApiService = serverApiService;
        solutionSvc = solutionService;
    }));


    it('should return all the solutions', function(done) {
        var account = {};
        account.id = '<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="384c5d4b4c784c5d4b4c165b5755">[email protected]</a>';
        solutionSvc.list(account).then(function(solutions) {
            expect(solutions.length).toBe(2);
            done();
        });

        expect(mockServerApiService.generateRequest).toHaveBeenCalled();

    })



});

Despite setting up the mock service, the 'then' portion in SolutionService is never executed:

serverApiService.generateRequest('solutions.list', data).then(function(response) {
                //Never called
});

To see a demonstration of the issue, check out this Plunker link: http://plnkr.co/edit/gMyaOpfczBmt9HhwzI9m?p=preview

Answer №1

Ensuring the resolution of a promise in Angular requires initiating an angular digest. To address this issue, I've made modifications to your plunk by introducing a new scope and invoking apply on it within your test scenario. For further details, refer to this link: http://plnkr.co/edit/Nrlg7KwfwTNJW3gpAG1m

var mockServerApiService, solutionSvc, scope;

    beforeEach(function() {
        module('test');
    });

    beforeEach(function() {
        module(function($provide) {
            $provide.service('serverApiService', function($q) {
                this.generateRequest = jasmine.createSpy('generateRequest').and.callFake(function(actionName, data) {
                    var deferred = $q.defer();

                    deferred.resolve({Items: [
                      {
                        Id: '910759',
                        Study: {
                          Id: '213123',
                          Name: 'test'
                        },
                      },
                      {
                        Id: '4406510',
                        Study: {
                          Id: '063294',
                          Name: 'test2'
                        },
                      }, 
                      ]});

                    return deferred.promise;
                });
            });
        });

    });



    beforeEach(inject(function (serverApiService, solutionService, $rootScope) {
        mockServerApiService = serverApiService;
        solutionSvc = solutionService;
        scope = $rootScope.$new();
    }));

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

Is there a way for me to access the property value utilized in the Cypress test?

I am currently working on a Cypress example that can be found at the following link: : cy.get('[data-test-id="test-example"]') .invoke('css', 'position') .should('equal', 'static') Despite my ...

Unable to locate template or render function for Vue Draggable Next component

Looking to incorporate Vue Draggable Next into a Vue 3 example page but encountering some challenges. I've attempted to follow the instructions in the repository. However, I ran into issues when importing the Vue Draggable Next component and had to re ...

Have developers created an event trigger for when google maps controls finish loading?

While I am aware of the tilesloaded event, it appears that the controls load after this event. My goal is to use jQuery to retrieve the controls, but I am struggling to identify the appropriate event to listen for. ...

What method can I use to adjust the font style when it overlays an image?

Sorry if this is a bit unclear, but I'm trying to figure out how to change only a section of my font when it overlaps with an image while scrolling. If you visit this example website, you'll see what I'm referring to: For a visual represen ...

What could be the reason for my image displaying when I manually input the src URL, but not when I set it through code?

While working on a practice React app, I encountered an issue with displaying an image from Firebase Storage on the website. Even though the image URL is correctly assigned to "src", the image does not appear on the site. Strangely, when I manually paste t ...

Create a React application that features a countdown timer using the new Date()

I have attempted to create a countdown timer, but I am encountering a problem with the getTime() function. This function calculates the remaining time by subtracting the current time from the finish time. However, the function is called multiple times ever ...

Changing marker colors dynamically in Google Maps with NextJS

I'm using the @googlemaps/js-api-loader package to load a map in my nextJS app. I have a list of locations that I want to plot on the map, and I also want these locations disabled on the left side of the page. When hovering over one of the locations ...

Tips for making objects rotate vertically on their axis and orbit around another object in three.js

Thank you in advance for all the support as I've been asking a lot of questions about my project. My project involves creating a simulation where a planet earth and moon rotate around a sun. (They're not exactly rotating around the sun, but more ...

Step-by-step guide on developing an AngularJs provider using TypeScript

As I've developed a Directive that incorporates various Css classes, it would greatly enhance its flexibility if the Css classes could be configured at Application start within the config section. I believe utilizing a provider is the appropriate appr ...

In Internet Explorer 8, experiment with creating a unique event in plain JavaScript and then capturing it using jQuery

Currently, I am facing an issue with IE8 regarding the execution order of scripts. There is a piece of code that needs to run before JQuery is loaded so I can fire a custom event. This event will be detected later by another section of code once JQuery ha ...

Implementing Facebook Javascript SDK to enable login and trigger re-authentication using React Web and Typescript within a component

As a newcomer to stack overflow, I welcome any suggestions on how I can improve my question. I'm in need of guidance concerning logging a user into facebook and requiring them to authenticate their profile or select another profile manually, rather t ...

Instructions on refreshing a webpage after choosing a sorting option using the onchange attribute

I'm encountering a small issue where the page won't refresh when I select a parameter from a dropdown list. Strangely, when I tested it on a separate document, there was no problem. I suspect Bootstrap may be causing a block somewhere. As someone ...

What is the best way to obtain a virtual in mongoose when a property is excluded?

Imagine I have a post Model with fields like UserId, Title, Desc, and a likes array which references UserIds. When querying, I have a virtual property to calculate the number of likes a post has: schema.virtual("numLikes").get(function () { return this. ...

Toggle the hamburger menu using JavaScript

How can I close my hamburger menu when clicking a link for one page navigation? The menu is functioning properly, but I need a way to close it. Unfortunately, I have limited knowledge of JS. I only have the HTML and CSS for this: HTML in index.html file ...

Understanding the process of retrieving a data value from HTML in an AngularJS directive

I'm a beginner with Angular and I'm trying to pass some data to my angular directive from the template. <div class="col-md-6" approver-picker="partner.approverPlan.data" data-pickerType="PLAN"></div> I h ...

Managing callback functions within an Angular 1.5 component

I am facing a challenge with handling callbacks in my Angular application. My goal is to load an image, convert it to base64 - which I have successfully achieved. However, I need to access the converted image data outside of the filesSelect.onchange; func ...

If the first returned function of the compose function is called without any arguments, what is the starting value of its reduce function?

In my attempts to modify the compose function to output to the console using different arguments, I am struggling to find a solution. The initial call of the compose function results in an undefined argument arg. Consequently, the reduce function utilizes ...

Display a field using React and JavaScript depending on the output of an asynchronous function

I'm working on an asynchronous function to query and return a value. Here's an example of what I have in mind: async function verifyProfileFeature(values: any) { const data = await client.query<any>({ query: PROFILE_QUERY, ...

Is the spread operator in React failing to function as anticipated?

In my current project, I encountered an issue while trying to pass a GeolocationCoordinates object to a child component using the spread operator. Strangely, in the child props, it appears as an empty object: interface HUDState { geoCoords: Geolocation ...

Strategies for passing a JavaScript variable to a JSP function

I'm dealing with a JavaScript code that has a value stored in its variable that I need to pass to my JSP function. However, I'm facing trouble passing it along. Take a look at the following code snippets: Javascript: $('button').on(& ...