Mastering the Art of Unit Testing JavaScript Asynchronous Code with Jasmine Mocking

Hello, I recently started learning JS and encountered a problem while testing asynchronous methods with jasmine mocking.

Below is the code snippet I am trying to test:

 test.factory('service', ['$http', '$q', function($http, $q) {
     var _func = function(varB, successCallback, errorCallback) {

         //Sanity check on input
         if (isNaN(varB)) {
             errorCallback('varB has to be a number');
             return;
         }

         if (parseInt(varB) < 0) {
             errorCallback('varB count has to be positive');
             return;
         }

         $http.get('http://www.test.com').then(function(response) {
             var data = angular.copy(response.data);
             if (successCallback) {
                 successCallback(data);
             }
         }, function(errorResponse) {
             if (errorCallback) {
                 errorCallback(errorResponse.data);
             }
         });
     };

     return {
         func: function(varB) {
             return $q(function(resolve, reject) {
                 _func(varB, resolve, reject);
             });
         }
     };
 }]);

One of the tests that I have written for this code snippet is as follows:

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

 it('should use the rejection handler if varB is in invalid format',
     function() {
         var successHandler = jasmine.createSpy('success');
         var failHandler = jasmine.createSpy('fail');
         service.func('abc').then(successHandler, failHandler);
         expect(successHandler).not.toHaveBeenCalled();
         expect(failHandler).toHaveBeenCalledWith('varB has to be a number');
     }
 );

However, I noticed that the line

expect(failHandler).toHaveBeenCalledWith('varB has to be a number');
never gets executed during the test. Even after adding debug statements in the service class, the mock was not detecting the callback being called with the specified argument.

If anyone has any insights or suggestions, I would greatly appreciate it! Thank you!

Answer №1

After some investigation, I was able to uncover the solution.

I came across helpful hints here.

The key was to implement a rootScope injection. Everything started working smoothly after that! :)

beforeEach(inject(function($injector) {
     service = $injector.get(
         'service');
     $httpBackend = $injector.get('$httpBackend');
     $rootScope = $injector.get('$rootScope');
 }));

 it('should trigger the rejection handler if varB is in an invalid format',
     function() {
         var successHandler = jasmine.createSpy('success');
         var failHandler = jasmine.createSpy('fail');
         service.func('abc').then(successHandler, failHandler);
         $rootScope.$digest();
         expect(successHandler).not.toHaveBeenCalled();
         expect(failHandler).toHaveBeenCalledWith('varB has to be a number');
     }
 );

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

encoding the special character "ü" in json_encode as either 'ü' or '&#

I've developed a function that extracts the title from a given URL and returns it in JSON format. The function is invoked by an AJAX call. Everything works smoothly, but when a title contains characters like ü or any related ones, it returns null. Wh ...

The function of adding data to a list in AngularJS seems to be malfunctioning

I have a JSON list that I am storing in an AngularJS variable called score $scope.jobTemplate = [{ type: "AddInstructions", visible: false, buttonText: "Add Instructions", editableInstructionsList: [{ Number: totalEditableInstruction, Text: "Instruction ...

Is there a performance benefit to using node.js over client-side JavaScript in comparison to Chrome/V8?

Currently, I am working on a client-side javascript application for image manipulation. However, some of the operations are running quite slowly in the browser, taking about 2-3 seconds to complete. To address this issue, I am considering implementing a s ...

The useSelector value remains undefined within the handleSubmit button in a React component

Once a user fills out and submits the form, the action is triggered to call the API. Upon returning the postId, it is stored in the reducer. The main React component then utilizes useSelector to retrieve the latest state for the postId. However, when attem ...

Implementing JSON object array retrieval from MySQL database and placing it into an empty array using AngularJS

Recently, I've been working on retrieving data from a MySQL database using PHP. Here is the snippet of code that I have written: $result = mysqli_query($con,"SELECT * FROM customers"); $return_arr = array(); while($row = $result->fetch_array(MYSQ ...

Repeating X and Y Axis Labels on Highcharts

Highchart is new to me. I recently created a basic chart showing the count of males and females over the past five years. I have included a screenshot for reference. I am wondering if it's possible to remove duplicate labels from both axes? Below is ...

Creating a Wireframe in Three.js Using a RawShaderMaterial with LineSegments

In the midst of my work on a project, I encountered a dilemma with rendering an intricate wireframe using THREE.LineSegments. My objective is to gradually animate the vertices within this LineSegments material (referred to as warehouse in the project), but ...

How can I effectively assign model data to a service property in an AngularJS controller?

I have established a service to facilitate the sharing of data/state across multiple controllers. One of the controllers updates certain properties within the service using scope data through a save function. The updated data is then accessed by other cont ...

The generation of the page fails due to the absence of defined data

Every time I try to start my server, the error message pops up saying 'data is not defined', even though I have already defined the data content. export default class App extends Component { data = [ { key: "john", val ...

Mongoose sparks a confrontation following the preservation of a single document in the database

I'm struggling to understand what minor mistake I'm making in this code. I have simplified the user schema to just one property, which is name. Initially, when I post the first entry to the database, it gets saved without any issues. However, whe ...

Can general principles be applied to determine which script is the most efficient and will load the quickest?

Is there a way to determine which script is optimal and will load faster when there are multiple ways to write scripts that achieve the same outcome? ...

What techniques can be used to avoid blinking while forcefully scrolling to the left?

In my previous inquiry about dynamically adding and removing divs on scroll, I was unable to find a satisfactory solution among the responses provided. However, I decided to take matters into my own hands and attempted to implement it myself. My approach ...

The logo marquee unexpectedly bounces up and down at the end of every

Struggling with a JavaScript code issue. The Logo marquee suddenly jumps at the end of each loop: I've tried everything, but I can't seem to fix it and make it work as intended Here's the complete script that technically works, but causes ...

Using a key as an argument in the `map` function invocation

I keep getting a warning message stating that each child in the array does not have a unique key. const ITEMS = [ { "name": "apple", displayName: "Apple" "name": "orange", displayName: "Orange" }, { "name": "banana", di ...

Inserting a value into a Node/Express session

I am currently immersed in a project that involves Node, Express, and MongoDB. Mongoose is the tool I use to shape my schemas and interact with the database. In addition, I utilize the "express-sessions" module where a session value named "req.session.user ...

Problem with single-table layout in DynamoDB and constraints on query parameters

I'm trying to limit the elements I fetch in each query, but encountered an issue: Using the single-table design in DynamoDB, I am only getting four items. If I check the first 10 elements in DynamoDB, I always get a count, regardless of my filtering ...

To validate any object, ensure that it contains a specific key before retrieving the corresponding value in typescript

When looking at a random object, my goal is to verify that it follows a certain structure. obj = {WHERE:{antherObject},OPTIONS{anotherObject}} Once I confirm the object has the key using hasProperty(key), how can I retrieve the value of the key? I thoug ...

Scrolling to the active list item in the navigation bar

Having an unordered list with the id mainul in the navigation bar is causing a problem when the page reloads. The navigation bar always starts at the beginning, but I would like it to automatically scroll to the active li element. This is my HTML code: & ...

A method for modifying the key within a nested array object and then outputting the updated array object

Suppose I have an array called arr1 and an object named arr2 containing a nested array called config. If the key in the object from arr1 matches with an id within the nested config and further within the questions array, then replace that key (in the arr1 ...

Is Jade used for making subsequent lines children of an included partial?

Recently, I've encountered an issue with a basic jade layout. Here is an example: include test.jade #bar hi In the test.jade file: #foo hello No matter what I try, the #bar element always ends up as a child of #foo. <div id="foo">hello &l ...