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

What's stopping me from using useState() to assign API data to an array?

I have a question regarding my app that makes use of the Movies API. I am making an API request and then passing the data to an array using the useState hook. Here is a snippet of my code: const App = () => { type MovieType = { rate: string, ...

A step-by-step guide on integrating Azure Cognitive Search within a SharePoint Online SPFx webpart

I haven't had much experience with SPFx recently, so it looks like I'll need to brush up a bit. :) I'm interested in implementing this NPM package: https://www.npmjs.com/package/azure-search Within a simple new SPFx web part: The code ...

Is it feasible to link an Angular property value to the value of an HTML data attribute?

Can an Angular property value be bound to a data attribute on a template element? <h1 data-name="{{name}}">Hello from {{ name }}!</h1> Example Link After running the code, it results in the following error: Error in src/main.ts (11: ...

The option value in mat-autocomplete is not displaying correctly on IOS devices

When I click on the first option in the dropdown menu, it does not display the selected option in the field. However, when I select the second option, then the value of the first option appears, and when I choose the third option, the value of the second o ...

What is the process for extracting the elements of an array fetched from a service in Angular 2?

Currently, I am learning Angular 2 + PrimeNG and going through a quick start project available at the following link: https://github.com/primefaces/primeng-quickstart The project is a CRUD application and it functions flawlessly. The data is neatly displa ...

How can I stop the SvelteKit production node server from filling up the logs with "Error: not found /path/here"?

After developing a website using sveltekit, I decided to build it for production as a nodejs server and deploy it on my linux server with Caddy as a reverse proxy. Unexpectedly, upon starting the server, I began receiving error messages in the log such as ...

Encountering an AngularJS 1.6 unit testing issue where the $scope is not defined, leading to a TypeError when trying to read the property 'setDescription' from undefined

While testing my angularjs 1.6.8 application with karma-jasmine, I keep encountering errors such as $scope is not defined and TypeError: Cannot read property 'setDescription' of undefined I have attempted to resolve these issues by searching onl ...

ES6 Update: Manipulating Nested Arrays with JavaScript

I have the following list of items: [ { idItem: "1", name: "apple", itemLikes: [{ id: "1", idItem: "1" }] } ] My goal is to simply add a new object to the itemLikes array. Here is my ...

Unit test failure attributed to misconfigured ECMAScript module setup

I am currently using Vue 3 along with Jest for testing purposes. I have created a simple code snippet to test, which is displayed below. Following some suggestions on Stack Overflow, I made some modifications to the babel.config.js and package.json files a ...

Incorporating a TypeScript interface into your Angular project

I recently started learning angular and I believe it's a good practice to include an interface in my code. The DataFetchService service is currently retrieving data from an internal .json file. Can someone guide me on the best approach to implement an ...

Unable to locate the "fcm-node" module in Node.js with TypeScript

When working on a TypeScript project, I usually rely on the fcm-node package to send Firebase push notifications in Node.js. However, this time around, I faced an issue. I know that for TypeScript projects, we also need to install type definitions (@types ...

Error: When trying to run the `ng build` command in Git Bash, TypeScript module cannot be

When attempting to execute ng build using Git Bash, I encountered this error message, even though I had previously executed npm install -g typescript. Where should I place the typescript installation so that Git can detect it? Error $ npm install -g typ ...

The sticky navbar fails to stay in place when the content becomes too lengthy

This is my current state of code (minified, for explanation only) index.html <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-w ...

[ERROR] There was a problem encountered during the execution of the ionic-app-scripts subprocess

I encountered an error while running my Ionic project. Below is the error message: [ERROR] ionic-app-scripts has unexpectedly closed (exit code 1). The Ionic CLI will exit. Please check any output above for error details. ionic3-firebase-shopping-car ...

Error: Type '() => () => Promise<void>' is not compatible with type 'EffectCallback'

Here is the code that I'm currently working with: useEffect(() => { document.querySelector('body').style['background-color'] = 'rgba(173, 232, 244,0.2)'; window.$crisp.push(['do', 'ch ...

Unable to retrieve selected value from Flowbite-React Datepicker due to malfunctioning props change event

I am encountering an issue with extracting the selected value from the Datepicker component in the flowbite-react library while using it with NextJS. The component is being displayed correctly. I attempted the code below, but it does not return anyth ...

Neglect variables that have not been declared (TypeScript)

Currently, I am working on developing a WebExtension using TypeScript that will be later compiled into JavaScript. This extension relies on one of the browser APIs offered by Firefox, specifically the extension API. An example of this is my use of the get ...

Unlocking the capabilities of Chrome extensions using Angular 2 and TypeScript

Currently attempting to develop a chrome extension using angular2 and typescript, I have hit a roadblock in trying to access the chrome API (in this case, chrome.bookmarks). I have successfully gained access to the chrome object by following guidance from ...

Tips for transferring information between two components when a button is clicked in Angular 2

I am currently working on a code that displays a table on the main page with two buttons, "Edit" and "Delete", for each row. When the Edit button is clicked, a modal opens up. My question is, how can I pass the "employee id" of a specific employee to the ...

Fixing the "Module not found" error in an Angular library using npm link

I'm currently working on creating an Angular wrapper for a Javascript library, but I've encountered a "Module not found" error. The Javascript library is still in development and has not been published to NPM yet. To work around this issue, I hav ...