Looking to simulate a constant instance that has been exported

Is there a way to mock the export const dependendantService in order for me to provide a mock result for dependendantService.list? The list contains a `get` method but it is read-only.

I have attempted to mock the module or use

jest.spyOn(dependendantService, 'list', 'get')
but I am encountering an error:

Cannot spyOn on a primitive value; undefined given

This scenario involves a Typescript class and an external module called dependency-service-instance.ts:

import { DependencyService} from './dependency-service';

export const dependendantService = new DependencyService();

Within my own module named my-service.ts, I have the following code:

export function myFunction(): string{

      // consuming here 

         const list = dependendantService.list;

       // doing something

}

For testing purposes using jest, I have another module named my-service-test.ts:

describe('test1', () => {
  it('should return a string if dependendantService does not return an empty list', () => {
    expect(myFunction()).toBe('xyz');
  });
});

Answer №1

To simulate a `getter` for the `list` property, you can utilize `jest.spyOn`. The solution is outlined below:

Directory structure:

.
├── dependency-service-instance.ts
├── dependency-service.ts
├── my-service.spec.ts
└── my-service.ts

dependency-service.ts:

export class DependencyService {
  private _list: any[] = [];
  public get list(): any[] {
    return this._list;
  }
}

dependency-service-instance.ts:

import { DependencyService } from './dependency-service';

export const dependentService = new DependencyService();

my-service.ts:

import { dependentService } from './dependency-service-instance';

export function myFunction(): string {
  const list = dependentService.list;
  if (!list.length) {
    throw new Error('list is empty');
  }
  return 'xyz';
}

my-service.spec.ts:

import { myFunction } from './my-service';
import { dependentService } from './dependency-service-instance';

describe('myFunction', () => {
  it('should return a string if dependentService does not provide an empty list', () => {
    const spy = jest.spyOn(dependentService, 'list', 'get').mockReturnValueOnce([{}]);
    const actualValue = myFunction();
    expect(actualValue).toBe('xyz');
    expect(spy).toBeCalledTimes(1);
    spy.mockRestore();
  });

  it('should throw an error if dependentService provides an empty list', () => {
    const spy = jest.spyOn(dependentService, 'list', 'get').mockReturnValueOnce([]);
    expect(() => myFunction()).toThrowError(new Error('list is empty'));
    expect(spy).toBeCalledTimes(1);
    spy.mockRestore();
  });
});

Unit test results with coverage report:

 PASS  src/stackoverflow/58073589/my-service.spec.ts (9.08s)
  myFunction
    ✓ should return a string if dependentService does not provide an empty list (5ms)
    ✓ should throw an error if dependentService provides an empty list (3ms)

--------------------------------|----------|----------|----------|----------|-------------------|
File                            |  % Stmts | % Branch |  % Funcs |  % Lines | Uncovered Line #s |
--------------------------------|----------|----------|----------|----------|-------------------|
All files                       |    92.86 |      100 |    66.67 |    92.31 |                   |
 dependency-service-instance.ts |      100 |      100 |      100 |      100 |                   |
 dependency-service.ts          |    83.33 |      100 |       50 |       80 |                 4 |
 my-service.ts                  |      100 |      100 |      100 |      100 |                   |
--------------------------------|----------|----------|----------|----------|-------------------|
Test Suites: 1 passed, 1 total
Tests:       2 passed, 2 total
Snapshots:   0 total
Time:        10.806s

For the complete demonstration, visit: https://github.com/mrdulin/jest-codelab/tree/master/src/stackoverflow/58073589

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

What are some strategies for distinguishing between callable and newable types?

I seem to be facing a challenge related to narrowing, specifically the differentiation between Fnc (callable) and Class (newable). The code snippet provided functions in Playground, but the autocomplete feature is lacking, as shown in the first image. My ...

Definition file in TypeScript for an npm package provided by an external source - constructor

In my Node project, I am utilizing ES6 and Typescript. Despite this, there is a commonjs library that I need to incorporate. To address this, I have created my own .d.ts declaration file for the library: module "@alpacahq/alpaca-trade-api" { e ...

The issue of unattainable properties in Angular2 FullCalendar callbacks

I am working on an angular2 application with a Full Calendar component. I am trying to show a dialog when a full calendar event is clicked using the eventClick callback. Below is the relevant code snippet: export class ScheduleComponent implements OnInit{ ...

Typescript for controlling the pause and resume functionality of a Bootstrap 4 carousel

I am creating a web application with Angular 4 and Bootstrap 4 beta. I need to pause the carousel when a user clicks on an image to display a modal, and then resume the carousel once the modal is closed. However, I have encountered an issue where changing ...

Creating a custom Map type in TypeScript

I am exploring the concept of defining a Map type in Typescript using generics. Essentially, I want to create something similar to: EntityMap<U, V>, where U can only be either a string or a number This is what I have managed to come up with so far: ...

Having trouble importing Sequelize in Angular?

I'm encountering an issue in my app where I am unable to import the sequelize package. The error message reads: chunk {main} main.js, main.js.map (main) 2.02 kB [initial] [rendered] chunk {polyfills} polyfills.js, polyfills.js.map (polyfills) 691 b ...

Sending asynchronous data to a child component in Angular 2

Having trouble with passing asynchronous data to a child component. I am attempting to create a dynamic form generator, but I encounter an issue when trying to fetch JSON data via an Observable and then passing it to the child component. Service: generat ...

Troubleshooting a Typescript issue with "padStart" while attempting to add an object to an array

In my code, I define an object template with empty values for publishedDate, Url, and Title: let dataTemplate = { publishedDate: "", Url: "", Title: "", } dataTemplate.publishedDate = xml.chi ...

Invoking a parent method from a child component in a TypeScript and React application

I'm facing an issue where I am unable to call a method from a parent component in my child component. The method in the parent element is not being triggered when the child component tries to call it. This problem is showcased in a simple example with ...

Tips on displaying hyperlinks within a text area in an Angular application

In my Angular application, I am facing an issue with displaying hyperlinks within a text area box for dynamic content. The hyperlinks are not recognized and therefore cannot be clicked. Can someone please advise on how to properly display hyperlinks with ...

Error: The FactoryMethod.render() function requires a valid React element to be returned, or null

An error has occurred: Error: FactoryMethod.render(): A valid React element (or null) must be returned. You may have returned undefined, an array, or some other invalid object. at invariant (react-dom.js:17896) Despite everything being fine during co ...

Managing checkbox states in Angular 2 using boolean values for both checked and unchecked options

Is there a way to dynamically check or uncheck a checkbox in Angular 2? Specifically, I want the checkbox to be checked automatically when the value is 1 and unchecked when the value is 0. public LightControl() { this.dataLight = this._LightService.Au ...

Implementing a feature in Typescript/React component that provides autocomplete functionality

Currently, I have developed a TypeScript and React component that has been published on NPM. My goal is to enable IntelliSense to autocomplete React props for this component. While I typically use JSDoc for plain React components, it does not seem to work ...

How is it that TypeScript still expects a valid return from an overridden method, even when it cannot be reached?

After creating a generic RESTClient with some abstract functions, I encountered an issue where not all REST actions are implemented. In these cases, I wanted to throw an error. The problem arose when trying to override the TypeScript method to both return ...

Compilation error in VueJS: missing dependency detected

I am facing an issue in my VueJS project where a file I am referencing seems to be causing a compilation error. Despite being present in the node_modules directory, the dependency is declared as not found. In the image on the left, you can see the directo ...

The Formik and React error is indicating that the '{ refetch: any; }' type is absent

When attempting to pass a prop down to my EmailSignupScreen, I encountered an error message. This issue arose while experimenting with Formik and Typescript. "message": "Type '{ refetch: any; }' is missing the following properties from type &apo ...

Combining objects with arrays to create a single unified data structure

I am trying to merge two array objects to achieve a specific structure, similar to the example below. "feedBackList" : [ { "questionNo" : 1, "scoring" : "5" }, { ...

Steps for TS to infer types on interfaces

Incorporated in my React application is an object that I devised. Within this object, there is the following definition for Props: type Props = { message: MessageTypes | MessageImgTypes; showTimeStamp: boolean; } If we assume that MessageTypes consists o ...

Issue TS2307: Module 'fs' or its type declarations cannot be located

I'm having trouble importing the fs module into my TypeScript component using import * as fs from 'fs'; I need it to use the writeFile method, as I want to extract data from an HTML form and write it to a JSON file. However, I am getting t ...

Show the name of the category in the mat table in Angular instead of the category

Using Angular Material Mat Table to display data fetched from an API is great, but I'm facing a challenge with handling categories from another API. Currently, my models include issues and categories, where the category ID is displayed instead of the ...