用Jest模拟在vue组件中导入的模块

时间:2018-09-30 18:51:37

标签: javascript unit-testing jasmine jestjs

我在处理documentation of Jest时遇到了一些问题,因为我希望这段代码可以工作:

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([ ... ]);
    // ...

但是不是。如果OrdersService从未被嘲笑过,它将失败。我也尝试过类似的东西:

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

第一个将整个服务替换为模拟功能(我想实现文档中提到的那种自动模拟功能,其中原始的所有方法都将被模拟fn自动替换)。 第二个失败与仅使用模块路径的.mock调用相同。

我在这里做错什么,为什么?

orders.service骨架:

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);

4 个答案:

答案 0 :(得分:1)

看来jest.mock#4262)涉及到moduleNameMapper的模块解析器,别名,路径等问题,无论您想使用@/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');

敬请关注有关该问题的最新动态,好像最新的更新是在9/28上。

第二,只要您解决了上述问题,就可以导出类实例,而不是类本身,就像Jest示例中那样。因此,您将无权访问clearMock上的OrdersService方法,而是可以在类实例上的每个模拟方法上调用clearMock

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

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

如果您想按原样导出实例,则可以在beforeEach中使用jest.clearAllMocks清除所有模拟,或循环遍历所有方法并在每个方法上调用mockClear。否则,导出类本身将使您能够访问OrdersService.mockClear,这将...

  

清除所有实例,并调用构造函数和所有方法(ref)

在嘲笑的类正在您要测试的另一个类中使用/实例化的情况下,这似乎很有用。

所有这些均已使用Jest v23.6和vue-cli v3.0.4进行了测试和确认。

答案 1 :(得分:1)

由于OrdersService是该类的实例,它将返回一个对象,您需要手动模拟此对象公开的所有属性。

您可以尝试以下实现来模拟您的功能。 Reference docs

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

希望这会有所帮助:)

答案 2 :(得分:0)

您可以尝试在jest.resetModules()块中调用beforeEach,这可能会导致模拟服务被使用

答案 3 :(得分:0)

尝试使用别名导入所有内容并在别名上设置模拟。

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

我在圣经中找到了它: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Modules