你如何使用 Jest 模拟外部库的命名导出构造函数和函数?



我见过类似的问题,但我在文档或stackoverflow中看到的任何内容都没有描述我正在尝试做什么。我是javascript的新手,刚刚开始使用jest,我已经通读了jest文档,但我还没有看到模拟外部库命名导出的示例。我试图模拟的库是速率限制器灵活的。我想嘲笑命名的导出 RateLimiterRedis。我需要模拟几个 RateLimiterRedis 函数,包括 get、consumption 和 delete。

例如,当我从redis嘲笑一个函数时,我所要做的就是:

import redis from 'redis';
jest.mock('redis', () => {
return { createClient: jest.fn()};
});

当我尝试时:

jest.mock('rate-limiter-flexible', () => {
return jest.fn().mockImplementation(() => {
return { RateLimiterRedis: { get: mockGet } }
});
});

我得到: 类型错误: _rateLimiterFlexible.RateLimiterRedis 不是构造函数

当我尝试时:

jest.mock('rate-limiter-flexible', () => {
return { RateLimiterRedis: () => {}}
});

我得到:TypeError:limiter.get 不是一个函数
所以它识别构造函数,但我需要添加函数。

我试过:

jest.mock('rate-limiter-flexible', () => {
return { RateLimiterRedis: () => {
return jest.fn().mockImplementation(() => {
return {
get: mockGet
}
})
},
}
});

这也给出了:TypeError: limiter.get 不是一个函数

这是我正在尝试测试的文件中:

const limiter = new RateLimiterRedis(opts);

我也尝试过 doMock 命名导出本身(因为模拟将自己提升到顶部(但没有成功

我的问题归结为,当该类是外部库的命名导出时,我如何模拟类的构造函数并且该类以开玩笑的方式运行?

编辑:
mock获取定义:

const mockIpAndUrl ={
consumedPoints:1
};
const mockGet = jest.fn().mockImplementation(() => {
return mockIpAndUrl;
})

这不起作用:

const mockIpAndUrl ={
consumedPoints:1
};
const mockGet = jest.fn().mockImplementation(() => {
return mockIpAndUrl;
})
jest.mock('rate-limiter-flexible', () => {
return{
RateLimiterRedis: jest.fn().mockImplementation(() => {
return { get : mockGet};
})
}
});

类型错误:limiter.get 不是一个函数

但是,这确实:

jest.mock('rate-limiter-flexible', () => {
return{
RateLimiterRedis: jest.fn().mockImplementation(() => {
return { get : jest.fn().mockImplementation(() => {
return mockIpAndUrl;
})};
})
}
});

这是我所指的文档: https://jestjs.io/docs/en/es6-class-mocks#calling-jestmockdocsenjest-objectjestmockmodulename-factory-options-with-the-module-factory-parameter

这让我相信我可以使用 mockGet

rate-limiter-flexible的导出是一个对象,它应该具有RateLimiterRedis函数,该函数返回具有get方法的实例。

"我试过了"片段是错误的,因为它使RateLimiterRedis函数返回另一个函数,并且RateLimiterRedis本身不是间谍,因此无法断言。

它应该是:

jest.mock('rate-limiter-flexible', () => {
return {
RateLimiterRedis: jest.fn().mockImplementation(() => ({
get: mockGet
})
};
});

如果在顶级导入中实例化RateLimiterRedis,则在模拟中访问mockGet之前无法分配。它可以导出为模拟模块的一部分:

jest.mock('rate-limiter-flexible', () => {
const mockRateLimiterRedisGet = jest.fn();
return {
mockRateLimiterRedisGet,
RateLimiterRedis: jest.fn().mockImplementation(() => ({
get: mockRateLimiterRedisGet
})
};
});

这允许从测试中的rate-limiter-flexible导入mockRateLimiterRedisGet,并用于动态模拟的值和断言:

mockRateLimiterRedisGet.mockReturnValue(...);
...
expect(mockRateLimiterRedisGet).toBeCalled();

最新更新