在 vitest 中使用模拟模块

问题描述 投票:0回答:1

我正在编写一个利用导入模块的实用程序,但我对如何正确模拟它有点困惑。

在实现中,我需要像这样调用导入模块周围的各种方法;

map = leaflet
    .map('map')
    .setView([38.58, -90.28], 15);

所以看来我需要两个级别的模拟:模拟

map
函数,然后模拟它返回的具有
setView
方法的对象。

在我的测试套件中,我有一个 beforeEach 生命周期钩子,它尝试模拟模块:

beforeEach(() => {
    vi.mock("leaflet", () => { // Mock the import itself

        // mocking the `Map` object returned from the `map()` function call
        vi.mock("leaflet.Map", () => { 
            return {setView: vi.fn()}
        })

        // mocking the `map()` function and returning the mocked `Map` instance(?)
        const mapMock = vi.fn()
            .mockImplementation((id) => {
                return new Map("")
            })

        // returning the object to replace the whole module import with
        return {
            default: {
                map: () => mapMock,
            }
        }
    })
})

但是当我在测试中使用它时:

it("can attach a map to the dom", () => {
    const config = new MapConfiguration(
        "map",
        new GeographicCoordinates(38.0, -90.0),
        15,
        19
    )

    attachMap(config)

    expect(leaflet.map).toHaveBeenCalled()
})

我收到一个奇怪的错误,我不确定它想告诉我什么

我毫不怀疑我在如何模拟模块方面误解了文档,但我不确定我做错了哪一部分。

vue.js unit-testing vitest
1个回答
2
投票

请记住,

vi.mock()
正在模拟整个模块,因此调用
vi.mock("leaflet.Map")
实际上并不起作用。 vi.mock()
path参数指的是正在导入的模块,因此要模拟“传单”模块,您需要
vi.mock("leaflet")
,然后适当地模拟这些函数的返回值。此外,在另一个模拟内部调用它是行不通的。无论如何,它们都会被提升到文件的顶部,因此将其放入
beforeEach
中不会执行任何操作。

要模拟传单,在最基本的层面上,类似以下内容就可以了:

import leaflet from "leaflet";
import { expect, it, vi } from "vitest";

vi.mock("leaflet", () => {
  return {
    default: {
      map: vi.fn().mockReturnValue({
        setView: vi.fn(),
      }),
    },
  };
});

it("can attach a map to the dom", () => {
  const config = new MapConfiguration(
    "map",
    new GeographicCoordinates(38.0, -90.0),
    15,
    19,
  );

  attachMap(config);

  expect(leaflet.map).toHaveBeenCalledWith("map");
});
© www.soinside.com 2019 - 2024. All rights reserved.