How can dependencies for an entire class or module be mocked in the mocha ecosystem similar to jest.mock?

I am currently working on unit testing a module that resembles the following code structure:

import { Countdown } from "./database/orm";

export class PersistentTimer {
    protected constructor(...) { ... }
    
    // To ensure database writing, constructor protection is used and construction is forced through an async interface
    public static async create(...) {
        const entity = new Countdown();
        // do something
        await entity.save();
        return new PersistentTimer(entity);
    }
}

In order to effectively test this module, I am in search of a mechanism similar to jest.mock within the mocha ecosystem to mock the Countdown module due to its side effects. Sinon appears to only handle functions, object properties, or instances passed to function calls.

Answer №1

If you need to simulate the ./database/orm module, you can use link seams.

In this case, since it's the CommonJS version, we will utilize proxyquire to create our seams.

For example:

main.ts:

import { Countdown } from './database/orm';

export class PersistentTimer {
  protected constructor(entity: Countdown) {}

  public static async create() {
    const entity = new Countdown();
    await entity.save();
    return new PersistentTimer(entity);
  }
}

main.test.ts:

import sinon from 'sinon';
import proxyquire from 'proxyquire';
import { expect } from 'chai';

describe('65399764', () => {
  it('should pass', async () => {
    const countdownInstanceStub = {
      save: sinon.stub(),
    };
    const CountdownStub = sinon.stub().returns(countdownInstanceStub);
    const { PersistentTimer } = proxyquire('./main.ts', {
      './database/orm': {
        Countdown: CountdownStub,
      },
    });
    const persistentTimer = await PersistentTimer.create();
    sinon.assert.calledOnce(CountdownStub);
    sinon.assert.calledOnce(countdownInstanceStub.save);
    expect(persistentTimer).to.be.instanceOf(PersistentTimer);
  });
});

unit test result:

  65399764
    ✓ should pass (1848ms)


  1 passing (2s)

-------------------|---------|----------|---------|---------|-------------------
File               | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s 
-------------------|---------|----------|---------|---------|-------------------
All files          |   85.71 |      100 |   66.67 |   85.71 |                   
 65399764          |     100 |      100 |     100 |     100 |                   
  main.ts          |     100 |      100 |     100 |     100 |                   
 65399764/database |      50 |      100 |       0 |      50 |                   
  orm.ts           |      50 |      100 |       0 |      50 | 3                 
-------------------|---------|----------|---------|---------|-------------------

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

Exporting Typescript to Javascript files

I have created a sample TypeScript object with the following code: declare const S3 = "https://s3.amazonaws.com/xxx/icons"; declare const SVG = "svg-file-icons"; declare interface MyIcons { "image/jpeg": string; "image/jpg": string; } export const F ...

Angular Error: Unable to access the 'title' property of an undefined value

Error Message Showing on Console for post-create.component.html ERROR Message: TypeError: Cannot read property 'title' of undefined at PostCreateComponent_Template (template.html:13) I suspect the issue is related to this line - console.log(for ...

Why Mixin Class inference is not supported in Typescript

I encountered an issue in my code: The error message 'Property 'debug' does not exist on type 'HardToDebugUser'.' was displayed. It seems like Typescript failed to infer the mixin class correctly. Can you please explain this t ...

Working with undefined covariance in TypeScript

Despite enabling strict, strictNullChecks, and strictFunctionTypes in TypeScript, the following code remains error-free. It seems that TypeScript is not catching the issue, even though it appears to be incorrectly typed. abstract class A { // You can p ...

Testing the functionality of an HTTP service in Angular 5 through unit testing

Testing a data service can be confusing with so many possibilities to consider. It's easy to feel overwhelmed. Consider this basic service: @Injectable() export class DataService { constructor(private _http: HttpClient) { } getData<T>(pa ...

The node command line does not recognize the term 'require'

My Typescript project was compiling and running smoothly until recently when I started encountering the error ReferenceError: require is not defined every time I try to run node. I am uncertain whether this issue stems from Typescript, as even when I ru ...

The absence of the import no longer causes the build to fail

Recently, after an update to the yup dependency in my create react-app project, I noticed that it stopped launching errors for invalid imports. Previously, I would receive the error "module filename has no exported member X" when running react-scripts buil ...

Storing Data Locally in Angular with User Authentication

Using angular8, I encountered an issue where logging in with USER1 credentials, closing the browser, and then attempting to log in with USER2 credentials still logged me in as USER1. While adding code to the app component resolved this problem, I faced an ...

Switching between various components based on conditions within the same route in Angular

My goal is to have 2 separate views, one for the homepage and another for authentication. I want to display the LoginComponent on the route '/' and the SignupComponent on the route '/signup' if the user is not logged in, otherwise rende ...

Clerk Bug: The UserResource type returned by useUser() does not match the @clerk/types

When attempting to pass the user obtained from useUser(), an error occurred: The 'UserResource' type is lacking the required properties 'passkeys' and 'createPasskey' from the 'UserResource' type Upon investigating ...

Creating valuable properties in TypeScript is a skill that requires knowledge and practice

In TypeScript, there is a unique feature available for defining properties with values using the `value` keyword. class Test { constructor(private value: number = 123) { } public MyValueProperty: number = 5; } Here is how you can define such ...

The sanitizer variable becomes null when accessed outside of the NgOnInit function in Angular using TypeScript

At first, I added DomSanitizer to the component: import { DomSanitizer, SafeResourceUrl} from '@angular/platform-browser'; Next, a class was created and included in the constructor: export class BlocklyComponent implements OnInit { primar ...

What causes the session storage to be accessed across various browser sessions?

Scenario While working on an application, I discovered an intriguing behavior in Chrome 62 on Windows 10 related to defining values in sessionStorage. Surprisingly, changing a value in one tab affected other tabs that shared the same key. Initially, I b ...

What is the best way to send parameters through the router in Next14?

Is there a way to pass parameters through the router with NextJS 14? I'm developing an app that features multiple items, and when a user clicks on one, they should be taken to that item's individual page. I'd like the URL to display as http ...

Trouble with importing React JSX from a separate file when working with Typescript

This problem bears some resemblance to How to import React JSX correctly from a separate file in Typescript 1.6. Everything seems to be working smoothly when all the code is contained within a single file. However, as soon as I move the component to anoth ...

How can you update the property values of a CSS class that already exists in an Angular2+ controller?

In my styles.css file, I have a CSS class called '.users' with a property of color. Now, I am looking to dynamically change the color property value of the 'users' class based on certain conditions in my controller. For instance, I want ...

Deriving union type in Typescript from values within a module or object

I'm trying to find a method similar to keyof typeof myModule in typescript. However, instead of a union of key strings, I need a union of the value types. I have a module with an increasing number of exports - myModule.ts: export const Thing1; expor ...

Steps for updating the same array in TypeScript

I have written a reducer code where I check if the same value is already present in the array. If it is, I update the previous value instead of pushing the same value again. Here is my code snippet: export function reducer( state: IDeviceState = ...

Using ngFor results in duplicate instances of ng-template

I'm facing a challenge with the ngFor directive and I'm struggling to find a solution: <ng-container *ngIf="user.images.length > 0"> <div *ngFor="let image of images"> <img *ngIf="i ...

What is the best way to inject a custom Angular service into a test in TypeScript without needing to mock it?

I have defined my modules and tests as shown below, but I encounter an issue when attempting to inject ContentBlocksService into the beforeEach(mock.inject((ContentBlocksService)... statement. It shows an error message saying Unknown provider ContentBlocks ...