Ways to simulate a dependent class in TypeScript & JEST without modifying constructor parameters to optional

Currently, I am attempting to replicate a well-known process in Java development using TypeScript and JEST for practice. In this scenario, there is a Controller class that relies on a Service class. The connection between the two is established through the constructor of the Controller, making the presence of the Service mandatory.

To manage dependencies at runtime, I utilize a Dependency Injection (DI) library called tsyringe. This ensures that the DI container handles the instantiation of the Service and its injection into the Controller when required.

Here is the source code for the Controller:

import { scoped, Lifecycle } from "tsyringe";
import { RouteService } from "./RouteService";
import { RouteDTO } from "./view/RouteDTO";

@scoped(Lifecycle.ContainerScoped)
export class RouteController {

    constructor(private routeService: RouteService) {}

    public createRoute(route: RouteDTO): RouteDTO {
        // business logic - meant for testing
        if (isBusinessLogicValid) {
            return this.routeService.saveRoute(route);
        } else {
            throw Error("Invalid business logic");
        }
    }
}

And here is the source code for the Service:

import { scoped, Lifecycle } from "tsyringe";
import { UserSession } from "../user/UserSession";
import { RouteDTO } from "./view/RouteDTO";

@scoped(Lifecycle.ContainerScoped)
export class RouteService {

    constructor(
        private userSession: UserSession
    ) {}

    public saveRoute(route: RouteDTO): RouteDTO {
        // contains business logic and handling persistence
        return route;
    }

}

I am striving to mock the RouteService class in a manner that eliminates the need for manual creation of an instance for unit testing purposes with the RouteController. If done manually, it would involve resolving all underlying dependencies (i.e., RouteController depends on RouteService, RouteService depends on UserSession, and so forth).

In Java, utilizing Mockito allows me to achieve something similar as shown below:

RouteService routeServiceMock = mock(RouteService.class); 
// defining mock behavior on routeServiceMock
RouteController controller = new RouteController(routeServiceMock);
RouteDTO newDTO = createRouteDTO();
RouteDTO savedDTO = controller.save(newDTO);
assertThat(savedDTO).isEqualTo(newDTO);
//... other assertions

Upon reviewing Jest documentation, I have not found an equivalent approach. Is there a way to accomplish this? If yes, could someone provide guidance on how to proceed?

Answer №1

After much trial and error, I believe I have stumbled upon a viable solution for the time being. However, I must admit, I am not entirely satisfied with the way this solution is structured. Essentially, I find myself having to perform a double cast using as unknown as RouteService.

Here is what I can do:

describe('Route controller test', () => {

    beforeEach(() => {
        let routeServiceMock: RouteService = {
            saveRoute: jest.fn(async route => route)
        } as unknown as RouteService
        routeController = new RouteController(routeServiceMock);
    })

   // ...
}

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

Flex-Layout in Angular - The Ultimate Combination

Recently, I decided to delve into Angular and the Flex-Layout framework. After installing flex-layout through npm, I proceeded to import it in my app.module.ts file like so: import { FlexLayoutModule } from '@angular/flex-layout'; imports: [ Fl ...

Discover the solution for seamless integration of TypeScript with the novel `exports` and `main` field

I am currently utilizing Node.js version 16.10.0 along with TypeScript 4.5.5. As part of my development process, I am in the midst of publishing a library and have implemented the following configuration: "main": "./dist/index.js", ...

Disregard any unrecognized variables associated with the third-party package

I've been working on integrating the bluesnap payment gateway into a react/ts project. I added their hosted javascript code to my public/index.html and started the integration within a component. However, when compiling, an error pops up saying ' ...

Can a function's return type be set to match the return type of its callback function?

Check out the following function export const tryAsyncAwait = async (fn: () => any) => { try { const data = await fn(); return [data, null]; } catch (error) { return [null, error]; } }; If I use this function as an example... const ...

Universal function for selecting object properties

I've recently delved into TypeScript coding and have run into a puzzling issue that has me stumped. Take a look at the code snippet below: interface testInterface { a: string; b: number; c?: number; } const testObject: testInterface = { a: & ...

Apollo Client is not properly sending non-server-side rendered requests in conjunction with Next.js

I'm facing a challenge where only server-side requests are being transmitted by the Apollo Client. As far as I know, there should be a client created during initialization in the _app file for non-SSR requests, and another when an SSR request is requi ...

What is the best way to declare only a portion of a JavaScript module?

I'm having trouble understanding declarations. If I only need to declare a portion of a module, is this the correct way to do it (disregarding the use of 'any')? import { Method as JaysonMethod } from 'jayson/promise'; declare cla ...

Encountering a 404 (Not Found) error while trying to access a null resource in Angular at http://localhost

Currently, I am developing an angular application with ng9. I have a specific div where I need to display an avatar using an image fetched from the API in my component.ts file: .... export class HomeComponent implements OnInit { nextLaunch$: Observabl ...

Enhancing Vue functionality with vue-class-component and Mixins

In my Vue project, I am using vue-class-component along with TypeScript. Within the project, I have a component and a Mixin set up as follows: // MyComp.vue import Component, { mixins } from 'vue-class-component' import MyMixin from './mixi ...

Is it possible to overlook TypeScript errors when compiling with Angular 2 AoT?

My application is experiencing numerous TypeScript errors, even though it runs correctly. I recently migrated a JavaScript app to TypeScript and am struggling to resolve all the type-related issues. In order to proceed with development, I have configured m ...

The problem encountered with the Enzyme mount API is a TypeError where it is unable to read the property 'find' of an undefined variable

After converting my component to a stateless one, I started encountering an error that says: TypeError: Cannot read property 'find' of undefined Previously, my tests were running smoothly before the switch. As far as I know, you can test functio ...

Prevent duplicate API calls in React with TypeScript

Upon page load, it is important to extract the value from the URL and send it to the API. However, due to changes in the state of parent objects, the API call is triggered three times when it should ideally only be called once. import React, {useContext ...

Having trouble getting material-ui container to work with custom breakpoints in TypeScript?

Currently, I am exploring material-ui and typescript within my educational project. However, I have encountered a perplexing issue for which I am seeking assistance. In this project, I utilize custom breakpoints in the material-ui theme settings. import { ...

Tips for utilizing Optical Character Recognition in Node.js with a buffer image:

Are you facing difficulties in creating an API that extracts data from an image without saving it on the server? Look no further, as I have a solution for you. When testing with the URL '', everything works perfectly. However, using a buffer or l ...

"Encountering a glitch in the Typescript/Node API where Express routes

Encountering a peculiar issue here - when attempting to import my router from an external file and add it as a route, I keep getting this unusual error where the string appears to be enclosed in double quotes. https://i.sstatic.net/nm9Wn.png ...

Cosmic - Ways to incorporate personalized validation strategies into the `getConfigValue()` function?

Why is the getConfigValue() function not retrieving validation values from custom Strategies? For example: @Injectable() export class CustomStrategy extends NbPasswordAuthStrategy { protected defaultOptions: CustomStrategyOptions = CustomStrategyOptio ...

The creation of a parameterized function that doubles as an object property

interface item { first: string; last: string; } const itemList = Item[]; updateAttribute = (index, attributeToUpdate) => { itemList[index].attributeToUpdate = "New first/last" } The snippet above showcases an interface named item with propertie ...

The cell must be crafted with a styling attribute to determine its placement

While working on my web app using React, I encountered a console warning: react_devtools_backend.js:4012 Rendered cell should include style property for positioning. at Grid2 (http://localhost:5173/node_modules/.vite/deps/react-virtualized.js?v=b41cc5 ...

Error: The Select2 query service is not available

I am looking to enhance the search functionality for my select2 dropdown. My goal is to trigger a service call with the search parameters once 3 characters are typed into the search field. However, when I try to select an option from the dropdown, I encou ...

Is there a way to turn off linting while utilizing vue-cli serve?

I am currently running my project using vue-cli by executing the following command: vue-cli-service serve --open Is there a way to stop all linting? It seems like it's re-linting every time I save, and it significantly slows down the process of ma ...