最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Mocking a module imported in a vue component with Jest - Stack Overflow

programmeradmin9浏览0评论

I'm having some issues processing the documentation of Jest, because I expected this code to work:

import Vue from 'vue';
import Router from '@/router/index';
import OrdersService from '@/services/orders.service';

jest.mock('@/services/orders.service');

describe('OrdersItem.vue', () => {
  beforeEach(() => {
    // mockClear does not exist
    OrdersService.mockClear();
  });

  it('should render expected list contents', () => {
    // Orders.mock is undefined 
    OrdersService.getAll.mockResolvedValue([ ... ]);
    // ...

However it does not. It fails as-if OrdersService was never mocked. I've also tried stuff like:

jest.mock('@/services/orders.service', () => jest.fn());
jest.mock('@/services/orders.service', () => { getAll: jest.fn() });

First one replaces the whole service with a mock function (I'd like to achieve that automatic mocking functionality mentioned in the docs, where all the methods from the original are auto-replaced with mock fn). Second one fails same way as the .mock call with just the module path.

What am I doing wrong here and why?

orders.service skeleton:

import axios from 'axios';
import config from '../config/config.json';
import Order from '../models/order';

class OrdersService {
  constructor(httpClient) {
    this.httpClient = httpClient;
  }

  getAll() {
      // ...
  }
}
export default new OrdersService(axios);

I'm having some issues processing the documentation of Jest, because I expected this code to work:

import Vue from 'vue';
import Router from '@/router/index';
import OrdersService from '@/services/orders.service';

jest.mock('@/services/orders.service');

describe('OrdersItem.vue', () => {
  beforeEach(() => {
    // mockClear does not exist
    OrdersService.mockClear();
  });

  it('should render expected list contents', () => {
    // Orders.mock is undefined 
    OrdersService.getAll.mockResolvedValue([ ... ]);
    // ...

However it does not. It fails as-if OrdersService was never mocked. I've also tried stuff like:

jest.mock('@/services/orders.service', () => jest.fn());
jest.mock('@/services/orders.service', () => { getAll: jest.fn() });

First one replaces the whole service with a mock function (I'd like to achieve that automatic mocking functionality mentioned in the docs, where all the methods from the original are auto-replaced with mock fn). Second one fails same way as the .mock call with just the module path.

What am I doing wrong here and why?

orders.service skeleton:

import axios from 'axios';
import config from '../config/config.json';
import Order from '../models/order';

class OrdersService {
  constructor(httpClient) {
    this.httpClient = httpClient;
  }

  getAll() {
      // ...
  }
}
export default new OrdersService(axios);
Share Improve this question edited Nov 2, 2018 at 9:33 skyboyer 23.7k7 gold badges62 silver badges71 bronze badges asked Sep 30, 2018 at 18:51 guessimtoolateguessimtoolate 8,6422 gold badges21 silver badges26 bronze badges 3
  • 1 Could you show the skeleton of the order.service? – Icepickle Commented Oct 2, 2018 at 21:07
  • I guess the problem here is that you are returning an instance, and not a class in itself – Icepickle Commented Oct 5, 2018 at 6:21
  • 1 @Icepickle could you explain? – guessimtoolate Commented Oct 5, 2018 at 8:04
Add a ment  | 

5 Answers 5

Reset to default 5

It looks like there is an issue in with jest.mock (#4262) concerning moduleNameMapper for module resolvers, aliases, path, whatever you want to call using @/something.

// you cannot use a module resolver (i.e. '@')
jest.mock('@/services/orders.service');

// you must use the full path to the file for the import and mock
import OrdersService from '../../src/services/orders.service';
jest.mock('../../src/services/orders.service');

Stay tuned to updates on the issue, looks like the last update was on 9/28.

Secondly, provided you fix the issue above, you are exporting a class instance not the class itself, as is done in the Jest example. Therefore, you will not have access to the clearMock method on the OrdersService but rather you can call clearMock on each mocked method on the class instance.

// mockClear will be undefined
OrdersService.mockClear();

// mockClear is defined
OrdersService.getAll.mockClear();

If you want to export the instance as you are, you could just clear all mocks using jest.clearAllMocks in the beforeEach or loop through all methods and call mockClear on each. Otherwise exporting the class itself will give you access to OrdersService.mockClear which will ...

Clear all instances and calls to constructor and all methods (ref)

This seems to be useful in cases where the mocked class is being used/instantiated in another class that you are trying to test, as in the jest example.

All of this has been tested and confirmed using Jest v23.6 and vue-cli v3.0.4.

Since the OrdersService is an instance of the class, it will return an object and you would need to mock all the properties exposed by this object manually.

You could try with the following implementation to mock your function. Reference docs

OrdersService.getAll = jest.fn(()=>{
// mock implementation here;
});

Hope this helps :)

You could try calling jest.resetModules() in the beforeEach block, that might cause the mocked service to be used

Try to import everything with an alias and set the mock on the alias.

import * as OrdersModule from '@/services/orders.service';
OrdersModule.getAll = jest.fn()

I found it in the bible: https://developer.mozilla/en-US/docs/Web/JavaScript/Guide/Modules

Running into this and had some issues with trying to get "mount" to work without having to manually set a bunch of things and the easiest way to get this work was importing the module:

import TestThisModule from 'testThisModule';

and then directly writing a spyon for the methods I watched to write tests for by accessing the module's prototype:

const resetMethodSpy = jest.spyOn(TestThisModule.prototype, 'reset');
const { wrapper } = factory();
await (wrapper.vm as any).triggerMethod();
expect(resetMethodSpy).toHaveBeenCalled();
发布评论

评论列表(0)

  1. 暂无评论