Encountered issue while jasmine mocking angular $http - Error: describe function does not support a done parameter

I am currently working with an angular factory that looks like this:

.factory('widgetFactory', ['$http', function($http){
  function getWidgets(){
    return $http.get('http://example.com/api/widgets/')
     .then(function(response){
        return response;
     });
  }
  return {
    getWidgets:getWidgets
  };
}])

Additionally, I have created a jasmine test for the widgetFactory:

describe('widgetFactory', function ($q) {
  var mockHttp,
  fakeResponse = 'response'
  beforeEach(function() {

    mockHttp = {
      get: jasmine.createSpy('get spy').and.callFake(function () {
        var deferred = $q.defer();
        deferred.resolve(fakeResponse);
        return deferred.promise;
      })
    };

    module(function ($provide) {
      $provide.value('$http', mockHttp);
    });

  });

  it('should properly call the API when getWidgets method is invoked', inject(function (widgetFactory) {
    var result;
    widgetFactory.getWidgets().then(function(response){
      result = response;
    });
    expect(mockHttp.post).toHaveBeenCalledWith('http://example.com/api/widgets/');
    expect(result).toBe(fakeResponse);
  }));
});

However, during testing, I encountered the following error message: "describe does not expect a done parameter"

After some investigation, I suspect the issue may be related to how I'm utilizing $q in my test. Other examples I've come across show the usage of inject(function($q){ ... inside the beforeEach block. Unfortunately, due to my use of module within the beforeEach, I end up facing another error: "Injector already created, can not register a module!". Any suggestions or insights on how to resolve this?

Answer №1

It is not possible to inject in the describe method. I have updated your code to utilize ngMock instead of mockHttp. This should help you understand how ngMock functions.

describe('widgetFactory', function () {
  var mockHttp,
  fakeResponse = 'response',
  getWidgetsDefer,
  getWidgetsPromise,
  $httpBackend,
  widgetFactory,
  $q;

  beforeEach(module('plunker'));

  beforeEach(inject(function($injector) {
    $httpBackend = $injector.get('$httpBackend');
    $q = $injector.get('$q');
    widgetFactory = $injector.get('widgetFactory');
  }));

  beforeEach(function() {
    getWidgetsDefer = $q.defer();

    $httpBackend.when('GET', 'http://example.com/api/widgets/')
      .respond(getWidgetsDefer);

    getWidgetsPromise = widgetFactory.getWidgets();
  });

   afterEach(function() {
     $httpBackend.verifyNoOutstandingExpectation();
     $httpBackend.verifyNoOutstandingRequest();
   });

  it('should call api when getWidgets is called', inject(function (widgetFactory) {
    expect($httpBackend.flush).not.toThrow();
  }));
});

You can check out the plunker example here

Answer №2

The 'done' function is an essential argument in Jasmine blocks, but not within the describe block. This error indicates a misunderstanding of how Angular services are injected without the proper use of the inject wrapper in Jasmine. Ignoring this crucial step cannot resolve the issue at hand.

One solution lies in utilizing angular.mock.module to mock services by providing an object argument. There's no need to reinvent the wheel when it comes to setting up these mocks.

However, mocked services may be self-contained and may not address issues with $q. Therefore, it becomes necessary to inject $q separately after configuring the module:


var $q;
beforeEach(function() {

    module({
      $http: { ... }
    });

    inject(function (_$q_) {
      $q = _$q_;
    });
})

Thankfully, ngMock offers a convenient $httpBackend mock, rendering the mocking of $http unnecessary. Real requests should not be triggered using ngMock. The test for the widget service can be succinctly written as follows:


widgetFactory.getWidgets();
$httpBackend.expect('GET', 'http://example.com/api/widgets/').respond(fakeResponse);
expect($httpBackend.flush).not.toThrow();

It's important to note that the order of mocking requests before or after the $http.get call does not matter. All pending requests are resolved upon calling $httpBackend.flush(). Additionally, checking that fakeResponse === fakeResponse can be omitted as it serves no purpose.

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

Tips for displaying errors when using AngularJS resources?

When attempting to display an error dialog when a web api request fails, I am utilizing bootbox for this purpose. The code snippet used is: OrderService.get(function(response) { $scope.newOrder = response; }, function(error) { $bootbox.alert(erro ...

Encountered a permission denial error (101) while attempting to upload a file to an SFTP server using SSH2 in

Encountering a permission denied error when attempting to upload a file to an SFTP server, whereas the same operation succeeds when using FileZilla. const UploadFiletoFTP = () => { let Client = require('ssh2').Client; var connSetti ...

Comparison of loading time between loader gif and browser's loading image

Recently, I've come across a code snippet where I implemented a 'loader' gif to show while PHP retrieves data from an SQL database. Everything seemed to be working fine when testing on my localhost. However, upon closer observation, I notice ...

Switch out bootstrap icons for angular material icons

I'm currently in the process of transitioning from using Bootstrap to Angular Material in an existing application. I need assistance with replacing the Bootstrap icons with Angular Material icons. Any help is greatly appreciated. <md-button class= ...

Tips for integrating jwt token into axios request

I am facing an issue with my backend endpoint. I can successfully retrieve a list of customers using jwt token on Postman, but when I try to fetch the list from a React app using axios get request, it fails. After reading through this question, I implemen ...

To ascertain whether the mouse is still lingering over the menu

I have a condensed menu construction that unfortunately cannot be changed in HTML, only CSS and JS modifications are possible! $('span').on("hover", handleHover('span')); function handleHover(e) { $(e).on({ mouse ...

Sort out videos for display based on a property in JSON using AngularJS

There are 4 buttons embedded in the HTML code. When any of these buttons is clicked, the videos should be filtered based on the "type" value found in the JSON data. Take a look at the code snippet below: <div class="btn-group hidden-xs" id = "selec ...

What is the process for selectively adding interceptors to app.module?

After searching through various topics, I have not found a solution that addresses my specific issue. To provide some context, we have an Angular App that operates in two modes - one mode uses one API while the other mode utilizes a different API. My goal ...

JQuery Ajax: Issue with updating Total Likes for posts when Like button is clicked

There are two JQuery Ajax calls in this scenario. The first call retrieves user messages from MySQL, along with the number of likes for each message and a button for users to like the message. This initial request is functioning correctly. The second Ajax ...

Click on the form to initiate when the action is set to "javascript:void(0)"

I am working on an HTML step form that needs to be submitted after passing validation and ensuring all fields are filled. The form currently has an action controller called register.php, but also includes action="javascript:void(0);" in the HTML form. What ...

Pixel information from previous canvas remains intact post resizing

I have crafted a canvas and loaded pixel data at specific locations using the following code snippet. let maskCanvas = document.createElement("canvas"); let patchWidth = 30; let patchHeight = 30; let scale = 3; maskCanvas.setAttribute("class", "mask"); ...

Do not include any null or empty objects when assigning to an array in Mongoose

When using mongoose's find() or findOne() methods, the returned value will be [] and null, respectively, if the where conditions are not met. This can cause issues when assigning these values to an array. Currently, I am filtering out the null values ...

Having trouble getting the onclick function to work in order to switch out the images

This is the HTML code that I used Here is the JavaScript code, but the onclick function seems to not be working ...

Attempting to transfer a property from one page to another using the Link component in NextJS

Currently, I have a page containing six Link elements that are meant to redirect to the same destination but with different props based on which link is clicked. To pass props, this is how I've implemented it: <Link href={{ pathname: '/pro ...

Adding custom data attributes to HTML tags in Vue.js

I have a question regarding adding a data attribute to the <html> element in vue.js (v2). I haven't been able to find any guidance on how to do this in the auto generated code or the documentation. The end goal is to achieve this desired output ...

Encountered an issue while sending JSON data back with PHP

Sharing data between server side code written in PHP and client side using Ajax can be accomplished like this: //server side $json='{ "payout_history":"0", "round_shares":"1816", "workers": { "jbo.5970": { "alive":"1", "h ...

Adjusting the height of a container dynamically in React while flex items wrap using CSS

In my React project, I have a container called "answers-container" with multiple buttons inside it, laid out using flexbox with flex-wrap: wrap to allow them to wrap onto the next line when the container width is exceeded. However, I'm facing an issu ...

How to implement a Typescript interface without necessarily implementing the parent interfaces

Within my current project, I have defined the following interfaces: interface foo { fooProperty: number; fooFunction(): void; } interface bar extends foo { barProperty: string; barFunction(): void; } Now, I am interested in creating a class like ...

What is the importance of installing gulp with --save-dev instead of just --save?

According to the information provided on the official documentation site, https://github.com/gulpjs/gulp/blob/master/docs/getting-started.md $ npm install --save-dev gulp In my experience, all npm modules are usually installed using $ npm install --sav ...

Guide on extracting value from XML data using $.ajax and then displaying it within a $.each loop

As part of our study project, we have a task that involves comparing an array of strings with an XML database. My approach was to break it down into two parts since we need to perform the comparison function twice. First, I iterate through the array using ...