Jasmine was unsuccessful in detecting a exported function being invoked by another function

In my code, I've created 2 helper functions where one is a shortcut to the other. I need to verify in my test that the shortcut function is actually calling the main function. Both functions are located in the same file:

export function test1(param1, param2, param3, param4) {
    return { param1, param2, ...(param3 && { param3 }), ...(param4 && { param4 }) };
}

export function test2(param1, param2) {
    return test1(param1, null, null, param2);
}

For the test case, I want to confirm that the first function is being called by the second function:

import * as Util from './my-util-file';
const test2 = Util.test2;
...
it('should call test1 when test2 is called', () => {
    const test1 = spyOn(Util, 'test1').and.callThrough();
    test2('test', 1);
    expect(test1).toHaveBeenCalledWith('test', null, null, 1);
});

Alternatively,

import {test1, test2} from './my-util-file';
...
it('should call test1 when test2 is called', () => {
    const test1Spy = jasmine.createSpy('test1');
    test2('test', 1);
    expect(test1Spy).toHaveBeenCalledWith('test', null, null, 1);
});

Or

import * as Util from './my-util-file';
const test2 = Util.test2;

...
it('should call test1 when test2 is called', () => {
    const test1Spy = spyOnProperty(Util, 'test1');
    test2('test', 1);
    expect(test1Spy).toHaveBeenCalledWith('test', null, null, 1);
});

Or

import {test1, test2} from './my-util-file';

...
it('should call test1 when test2 is called', () => {
    const test1Spy = spyOn(window as any, 'test1');
    test2('test', 1);
    expect(test1Spy).toHaveBeenCalledWith('test', null, null, 1);
});

However, I encountered the following error:

Expected spy test1 to have been called.

Answer №1

This is not an error specific to jasmine. It is a common behavior of JavaScript modules after compilation or transpilation.

var test1 = function test1() {};
var test2 = function test2() { test1(); };

exports.test1 = test1;
exports.test2 = test2;

When the function test2 is defined, it encapsulates a reference to the test1 function within its declaration. However, what we actually import in the specifications are exports.test1 and exports.test2. This means that we end up spying on something unintentionally, which is exports.test1.

To properly retain the reference, we can define and export the test functions as shown below:

const test1 = function(param1: any, param2: any, param3: any, param4: any) {
  return { 
    param1,
    param2,
    ...(param3 && { param3 }),
    ...(param4 && { param4 })
  };
};

const test2 = function(param1: any, param2: any) { 
  return testFunctions.test1(param1, null, null, param2); // Here, we ensure the reference is maintained
};

export const testFunctions = {
  test1,
  test2
};

These functions can then be tested as follows:

import * as test from './test';

const functions = test.testFunctions;

it('should invoke test1 when test2 is called', () => {
    const test1 = spyOn(functions, 'test1').and.callThrough();
    functions.test2('test', 1);
    expect(test1).toHaveBeenCalledWith('test', null, null, 1);
});

For further insights into this issue, you can refer to this informative article.

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

One issue that may arise is when attempting to use ngOnDestroy in Angular components while rearranging user transitions

Encountered an issue recently with Angular - when the user navigates from component A to component B, component A remains active unless ngOnDestroy is triggered. However, if the user visits component B before going to component A and then leaves, ngOnDes ...

The Angular directive ng-if does not function properly when trying to evaluate if array[0] is equal to the string value 'Value'

In my code, I want to ensure that the icon is only visible if the value at array index 0 is equal to 'Value': HTML <ion-icon *ngIf="allFamily[0] === 'Value'" class="checkas" name="checkmark"></ion-icon> TS allFamily = [ ...

Tips for implementing server-side pagination using NestJS

Working with a MEVN stack that includes Nestjs, MongoDB (mongoose), I am currently tackling the task of setting up server-side pagination. I've decided to utilize mongoose-aggregate-paginate-v2 for this purpose, but so far, I haven't been able to ...

Issue with Datatables not loading on page reload within an Angular 7 application

Incorporating jQuery.dataTables into my Angular 7 project was a success. I installed all the necessary node modules, configured them accordingly, and added the required files to the angular.json file. Everything functioned perfectly after the initial launc ...

Angular 4 Issue: Child Routing Dysfunction

I'm encountering an issue with the child routing in Angular 4. The parent routing is functioning correctly, but when I hover over "Create New Account," it remains on the Account page instead of redirecting to localhost:4200/account/create-account. The ...

Using TypeScript, the Generator functions in Redux Saga do not execute nested effects in sequence when using yield put

I need to handle multiple asynchronous actions and ensure that a third action is only triggered after the first two have successfully completed. I have created three saga workers for this purpose: export function* emailUpdateRequestSaga(action: IEmailUpda ...

Writing Data to Google Cloud Firestore Map using NextJS and Typescript with nested objects

I could use some assistance. I'm developing an application using NextJS (React), TypeScript, and Google Cloud Firestore. Everything seems to be working fine so far. However, I'm facing an issue with storing the address and phone number in a neste ...

Error message "Cannot bind to 'name' because it is not a recognized native property" encountered in Ionic icon configuration

Currently, I am developing a mobile app using Ionic 2 and Angular 2. I encountered an issue when trying to use the [name] property in conjunction with Ionic icons and expressions like this: <icon item-right [name]="result.kind ==='song&apo ...

What is the method for filtering out specific fields in a template string?

I am currently working on defining constraints for the method field type event = { [k: `on${string}`]:(e:string)=>void } However, I need the event argument to be a number for fields that do not begin with 'on' type event = { [k: ` ...

Angular2 form builder generating dynamic forms based on results of asynchronous calls

When creating my form, I encountered a challenge with passing the results of an asynchronous call to the form builder. This is what I have attempted: export class PerformInspectionPage implements OnInit { checklists: any; inspectionform: FormGroup; n ...

Issue with Angular2 formBuilder: two validators are not functioning as expected

Need help with a text input that is required and must be longer than 3 characters. When clicking on the input, if a user types something shorter than 3 characters and then clicks out, a red border should be added. Otherwise, the border should be green. ...

Creating a channel for communication between sibling components in Angular 4 by storing component references in a shared service

I am searching for a way to establish communication between two sibling Angular 4 components. After reviewing the documentation at https://angular.io/guide/component-interaction, my idea revolves around utilizing a service that stores a reference to the c ...

Utilize the automatically detected type of an object for utilization in a Generic context in Typescript

The Scenario I am experimenting with the combination of Alpine.js and TypeScript. To achieve this, I am utilizing the community-maintained typings package @types/alpinejs (GitHub) along with the reusable components design pattern outlined here. Here' ...

"After updating to version 3, the Ionic 3 component's JavaScript is failing to refresh properly

During the development of my Ionic 3 app, I encountered what I believe is a cache issue. It seemed to be related to lazy loading components as the problem arose after upgrading to v3 and activating lazy loading. While in development mode and using ionic se ...

Enhanced string key indexer type safety in TypeScript

Discover and explore this online TypeScript playground where code magic happens: export enum KeyCode { Alt = 'meta', Command = 'command', // etc. } export type KeyStroke = KeyCode | string; export interface Combination { comb ...

Is it possible to establish multiple connections simultaneously using Stomp?

I have been utilizing the ng2-stomp-service in my Angular application. Is it advisable to set up multiple connections (not just multiple subscriptions)? In the past, I have always seen a single connection being established, with several subscriptions made ...

Utilize NestJS to retrieve information from an observable gRPC service

One of the challenges I am facing is using gRPC service to facilitate communication between my microservices. Specifically, when receiving a response from the Grpc service, I need to apply some modifications and additional functionality before returning a ...

Having trouble with Nextjs API Integration - encountering error 404

I'm currently facing a major issue and I've hit a dead end. I've been spending days trying to connect my local nextjs 14 app to the CVENT API, but I keep receiving a persistent 404 error. Here's what is displayed in the frontend console ...

Encountering a CORS problem when an Angular application communicates with a .NET Core API integrated with the Sustainsys.Saml2 library and Azure Active Directory serving as the Identity

Our team is currently working on implementing SAML authentication in a .NET Core API to handle requests coming from an Angular application. We are utilizing the package Sustainsys.Saml2.AspNetCore2 (version 2.9.2) for .NET 6, and we have successfully set u ...

Creating OL maps with subpar quality using the Ionic framework

I'm currently facing an issue while trying to load the OL map with Ionic. When I use 'ionic serve' to load it, the map displays perfectly in the browser. However, when I try to load the map on a mobile device, the quality drastically decreas ...