【问题标题】:Mocking a module imported in a vue component with Jest使用 Jest 模拟在 vue 组件中导入的模块
【发布时间】:2019-03-05 23:18:31
【问题描述】:

我在处理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);

【问题讨论】:

  • 你能展示一下order.service的骨架吗?
  • 我猜这里的问题是你返回的是一个实例,而不是一个类本身
  • @Icepickle 你能解释一下吗?

标签: javascript unit-testing jasmine jestjs


【解决方案1】:

jest.mock (#4262) 中似乎存在一个问题,涉及到模块解析器、别名、路径以及任何你想使用 @/something 调用的 moduleNameMapper

// 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 示例中所做的那样。因此,您将无法访问 OrdersService 上的 clearMock 方法,而是可以在类实例上的每个模拟方法上调用 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 进行了测试和确认。

【讨论】:

  • 谢谢伙计,我很欣赏这项研究。然而,在我的特殊情况下,将导入语句切换为使用相对路径似乎并没有为我解决这个问题。最后,我使用手动模拟,在模拟模块旁边创建__mocks__ 目录并放弃 es6 类,转而使用方法导出对象文字。我觉得它不是很优雅,但到目前为止它似乎工作。现在我遇到了其他问题,所以很可能我的原始问题也将通过对 jest (22.0.4)、vue-test-utils (1.0.0-beta.25, sic)、babel-jest (21.0) 的一些更新来解决.2) 等等。
  • 别担心,很抱歉这对您的情况不起作用。是的,我通常只是嘲笑我需要的东西,而忽略其余的。
【解决方案2】:

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

您可以尝试使用以下实现来模拟您的函数。 Reference docs

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

希望这会有所帮助:)

【讨论】:

    【解决方案3】:

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

    【讨论】:

      【解决方案4】:

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

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

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2019-04-10
        • 2023-03-11
        • 2021-01-21
        • 2018-04-28
        • 2019-04-01
        • 1970-01-01
        相关资源
        最近更新 更多