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

Arrange data in JSON file based on job title (role name) category

My current code successfully outputs data from a JSON file, but I'm looking to enhance it by organizing the output based on the "Role Name". For example, individuals with the role of Associate Editor should have their information displayed in one sect ...

Cannot transfer variables from asynchronous Node.js files to other Node.js files

Is there a way to export variable output to another Node.js file, even though the asynchronous nature of fs read function is causing issues? I seem to be stuck as I am only getting 'undefined' as the output. Can someone help me identify where I ...

Converting JSON to string in Typescript is causing an error where type string cannot be assigned to type '{ .. }'

Here's the code snippet I'm working with: interface ISource extends IdModel { source_type_id: number; network_id: number; company_connection_id: number; feed_id: number; connection_id: number; feed_ids: number[]; name: string; tag ...

The Google timezone API is displaying an inaccurate daylight saving offset

London now has an additional +1 hour of daylight saving time. I made a request to the Google timezone API for the London timezone, but unfortunately, it is not displaying the correct time. https://maps.googleapis.com/maps/api/timezone/json?location=51.507 ...

Retrieve the child DIV element within its sibling without using an identifier

I have a setup similar to the following: <div class="panel panel-primary"> <div class="panel-heading"> <h3 class="panel-title">Tiger128 (v2)</h3> </div> <div class="panel-body"> <inp ...

What causes the text field and checkbox to move downward as I enter text?

I'm currently working on a mock login page using React and Material UI. I implemented a feature where the show/hide password icon only appears when the user starts typing in the password field. However, after making this change, I noticed that the pas ...

Removing information from a MongoDB database with the help of AngularJS and Node.js

Having trouble deleting data in MongoDB using AngularJS and Node.js, as I keep encountering the error "Cannot DELETE /api/manage-product" in the console. .html file <tbody> <tr ng-repeat="product in vm.result"> ...

What is preventing me from using JavaScript to generate labels?

My current project involves creating dynamic input fields to filter products by color. I initially attempted static checkbox inputs for this purpose, which worked fine. Now, I want to achieve the same functionality but dynamically through JavaScript. Inste ...

Issue encountered while loading JSON data into DynamoDB's local instance

I have successfully set up DynamoDB local and everything is functioning as expected after going through their documentation. I have also tested their example code, which worked flawlessly. The Users table has been created with the name "Users". Below is ...

Unleash the Power of Animating Your Active Tabs

Is there a way to create animated tabs that slide in when clicked? I've experimented with using transition code but haven't quite achieved the desired effect yet. This is what I currently have: [data-tab-info] { display: non ...

Associate a click event to a dropdown menu element to trigger on selection

My issue involves having multiple select elements. When one of them is changed, I am trying to bind a click event only to its next element with the .btn class. Below is the code snippet illustrating my problem: <div class="whole"> <ul> ...

After the completion of the JavaScript timer, the existing text remains in place even when the new text is displayed

https://jsfiddle.net/zLfuwdtu/1/ I've developed a script that tracks down to date 'Date1'. As it counts down, it shows the message "UNTIL FLOW." Once this timer reaches zero, another timer 'Date2' takes its place and displays "ON ...

Trigger a function when clicking outside the element, similar to how a Bootstrap modal is closed

I have successfully created a popup box using angular in my project. It appears when I click on an icon and disappears when I click on the close button. However, I would like it to also close if someone clicks outside of the popup. Can anyone help me with ...

Instructions on utilizing the transpiled "main.js" file using gulp

As a novice in Angularjs 1.0, I encountered issues with my script and decided to use gulp to compile ec6 to ec5 by implementing the code provided below. The compilation process generated the file main.js. However, I am unsure about how to connect it when l ...

Guide to making a Grid element interactive using the Link component

PostsList component is responsible for rendering a list of posts. The goal is to enable users to click on a post item and be redirected to the specific post's link. const PostsListView = ({ posts, setError, isloggedin }) => { const [redirectCre ...

Can you suggest a method using Lodash to remove specific rows from an array based on the value of a certain field within the array?

Currently, I am utilizing the following function: remove: function (arr, property, num) { for (var i in arr) { if (arr[i][property] == num) arr.splice(i, 1); } }, Although this functi ...

Peruse a spreadsheet for relevant information

I am currently facing an issue with a search bar that I implemented to filter through a table. However, for some reason, the filtering function does not seem to work on the tbody section of the table. The content in the tbody is generated dynamically usi ...

AngularJS Uncaught ReferenceError: variable is not

I am facing an issue where I cannot retrieve a value from a function. I am performing REST requests for testing purposes and when trying to get a date, it always returns undefined. An Illustration $http.get('app/components/home/controller/test_calen ...

Why does my Observable remain perpetually unfulfilled?

I recently started learning javascript and came across the Angular 2 Documentation where I discovered that Promises can be replaced with Observables. While experimenting with a simple code, I noticed that in addition to the expected result, I am also getti ...

Retrieving registered components dynamically in Vue.js

Check out my scenario on jsBin In my setup, I have a selector <component :is="selectedComponent"></component>, along with a <select v-model="currentComponent">...</select> that allows me to choose which one is displayed. Currently ...