Ways to simulate a function that is a part of an internal object

Is there a way to mock a method from an object within my UnderTest class?

When the Update method is triggered by an event from a child component, I need to mock the service.saveNewElement(data) method in order to test data in the then() block.

<script lang="ts">
import { Component, Prop, Vue } from 'vue-property-decorator';
import { Service } from 'secret';
import ROUTES from '../../../../router/routes.const';


@Component({
    name: 'UnderTest',
    template: require('./underTest.component.html'),
})
export default class UnderTest extends Vue {
    private service: Service;

    constructor() {
        super();
        this.service = new Service();
    }

    public update(data: any): void {
        this.service
            .saveNewElement(data)
            .then(() => {
                //stuff to do
            })
            .catch(() => {
                this.$notify.error('Oops!, sth went wrong...');
            });
    }
}
</script>

Any suggestions on how to accomplish this?

EDIT:

I tried the suggestion from @slideshowp2 but encountered another issue.

I used the following code snippet in my test file:

jest.mock('../../services/customer.service',() => ({
    constructor: jest.fn(() => {}),
    saveNewCustomer: jest.fn(() => Promise.resolve({ data: 3 }))
}));

This resulted in an error:

[Vue warn]: Error in data(): "TypeError: service.Service is not a constructor"

Can anyone provide guidance on resolving this?

Answer №1

To simulate the behavior of the imported Service, you can manually mock it by using jest.mock(moduleName) and placing your mocked Service in the __mocks__ directory. I have provided a sample setup for reference:

The file structure should look like this:

.
├── __mocks__
│   └── someService.ts
├── index.spec.ts
├── index.ts
└── someService.ts

someService.ts:

class SomeService {
  public async saveNewElement(data) {
    return 'real data';
  }
}

export { SomeService };

index.ts:

import { SomeService } from './someService';

export default class UnderTest {
  private service: SomeService;

  constructor() {
    this.service = new SomeService();
  }

  public update(data: any): any {
    return this.service.saveNewElement(data).then(res => {
      // stuff to do
      console.log(res);
    });
  }
}

__mocks__/someService.ts:

const mockedSomeService = {
  saveNewElement: jest.fn().mockResolvedValue('mocked data')
};
const SomeService = jest.fn(() => mockedSomeService);

export { SomeService, mockedSomeService };

Now for the unit test:

import UnderTest from './';

jest.mock('./someService.ts');

const underTest = new UnderTest();

describe('UnderTest', () => {
  it('t1', async () => {
    console.log = jest.fn();
    await underTest.update('jest');
    expect(console.log).toBeCalledWith('mocked data');
  });
});

The unit test result should show success:

 PASS  src/stackoverflow/57775960/index.spec.ts
  UnderTest
    ✓ t1 (14ms)

Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        0.911s, estimated 2s

=================UPDATE================

An alternative approach is to mock the imported module without using the __mocks__ directory. This can be achieved through jest.mock(path, moduleFactory).

import UnderTest from './';

const mockedSomeService = {
  saveNewElement: jest.fn().mockResolvedValue('mocked data')
};

jest.mock('./someService.ts', () => {
  return {
    SomeService: jest.fn(() => mockedSomeService)
  };
});

const underTest = new UnderTest();

describe('UnderTest', () => {
  it('t1', async () => {
    console.log = jest.fn();
    await underTest.update('jest');
    expect(console.log).toBeCalledWith('mocked data');
  });
});

It's recommended to utilize Dependency Injection Principle (DIP) for easier mocking and injecting of dependencies. Import abstract classes/interfaces instead of concrete classes like SomeService.

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

The Vue instance seems to be unable to recognize the shims-vue.d.ts file

I encountered an issue with my Vue file. Here is the code snippet: import Vue from 'vue'; import VueRouter from 'vue-router'; export default Vue.extend({ name: 'MyComponentsName', methods: { doRedirect() { this. ...

How can a class be imported into a Firebase Cloud function in order to reduce cold start time?

When optimizing cold start time for Firebase Cloud functions, it is recommended in this Firebase Tutorial to import modules only where necessary. But can you also import a class with its own dependencies inside a function? In my scenario, I need to use Bc ...

Updating a boolean prop does not cause the child component to be refreshed

I am working with the following components: Parent: <template> <Child path="instance.json" v-bind:authenticated="authenticated" v-bind:authenticator="authenticator" /> </tem ...

After the rendering process, the React Component member goes back to a state of

One issue I encountered is related to a component that utilizes a separate client for making HTTP requests. Specifically, when trying to use the client within a click event handler, the call to this.client.getChannel() fails due to this.client being undefi ...

Is there a way to automatically scroll to the bottom of a div when it first

Looking to enhance my application with a chat feature that automatically scrolls to the bottom of the chat page to display the latest messages. Utilizing VueJs: <template> <div id="app"> <div class="comments" ...

Raycasting in Three.js is ineffective on an object in motion

Working on a project that combines three.js and typescript, I encountered an issue while attempting to color a sphere by raycasting to it. The problem arises when the object moves - the raycast doesn't seem to acknowledge the new position of the objec ...

Changing return values with Jest mocks in TypeScript

Here I am again with a very straightforward example. In summary, I require a different response from the mocked class. Below is my basic class that returns an object: class Producer { hello() { return { ...

What is the best way to adjust and filter an array based on a single value?

Here is an array that needs to be modified: [ {name: "test", value: "test", group: 0}, {name: "test1", value: "test2", group: 0}, {name: "test3", value: "test3", group: 1}, {name: "te ...

What steps should I take to address conflicting type identifiers between Cypress and jQuery?

Currently, I am tasked with writing TypeScript end-to-end tests for an Angular 11 application. Following the recommended practices of Cypress, my test setup is encountering a conflict due to existing jQuery dependencies (3.5.1) in the app and Cypress (8.4. ...

Ways to verify if a function has completed execution and proceed to invoke another function

I am seeking to verify if a user has chosen an item from the ngFor form and then redirect them to another page upon submitting the form with the updated value. HTML: <mat-select placeholder="Treatment" [(ngModel)]="model.TreatmentA" name="TreatmentA" ...

Converting an array of objects to an array based on an interface

I'm currently facing an issue with assigning an array of objects to an interface-based array. Here is the current implementation in my item.ts interface: export interface IItem { id: number, text: string, members: any } In the item.component.ts ...

Leverage context to facilitate communication between components operating at various levels of the system

I am currently working on the settings pages of my applications. Each page features a common SettingsLayout (parent component) that is displayed across all settings pages. One unique aspect of this layout is the presence of an ActionsBar, where the submit/ ...

Angular 5 - Creating a dynamic function that generates a different dynamic function

One of my latest projects involved creating a versatile function that generates switch-case statements dynamically. export function generateReducer(initialState, reducerName: ReducerName, adapter: EntityAdapter<any>): (state, initialState) => ISt ...

How do I remove a specific object from my localStorage array in Angular?

Currently, I am storing and retrieving form values from localStorage. When displaying the data, I want to be able to remove a specific object that is clicked on. The issue is that my current code removes all the data instead of just the selected object. Be ...

A Typescript object that matches types and eventually returns a string when called upon

In the process of overengineering a type that can match either a string or an object whose valueOf() function, when evaluated recursively, ultimately returns a string. type Stringable = string | StringableObject; interface StringableObject { valueOf() ...

Organizing string enum in Typescript and AngularJS - Tips and Tricks

In my Typescript file, I have defined an enum called PriorityLevel: enum PriorityLevel { High = <any>'High', Normal = <any>'Normal', Low = <any>'Low'} In the HTML section, I have the following code: <b ...

Update the headers of the axios.create instance that is exported by Axios

I have a single api.js file that exports an instance of axios.create() by default: import axios from 'axios' import Cookies from 'js-cookie' const api = axios.create({ baseURL: process.env.VUE_APP_API_URL, timeout: 10000, headers ...

transform array elements into an object

I encountered the following code snippet: const calcRowCssClasses = (<string[]>context.dataItem.cssClasses).map( (cssClass) => { return { [cssClass]: true }; } ); This code block generates an array of objects like ...

Identify and handle errors effectively using TypeScript

I have a question regarding my Express server setup. Here is the code snippet: import express from "express"; import helmet from "helmet"; import cors from "cors"; const app = express(); app.use(helmet()); app.use(cors()); a ...

Utilizing shared state in React components through props

Currently, I am utilizing a shared global state in the following manner: interface DashboardProps extends React.Props<Dashboard> { globalState? : GlobalState } export class Dashboard extends React.Component<DashboardProps, any>{ } Withi ...