模拟 es6 模块返回工厂函数(moment.js)
Posted
技术标签:
【中文标题】模拟 es6 模块返回工厂函数(moment.js)【英文标题】:Mocking es6 module returning factory function (moment.js) 【发布时间】:2018-11-30 01:13:36 【问题描述】:警告:我是 Jest 的新手,所以请忍耐。
我正在尝试使用名为 DateFilter 的 Jest 测试 Vue2.js 过滤器。此过滤器只是将日期格式应用于传递给它的日期。
日期过滤器.js
import Vue from 'vue';
import moment from 'moment';
const dateFormatter = (dateValue, dateFormat) =>
return moment(dateValue).format(dateFormat);
;
Vue.filter('date', dateFormatter);
export default dateFormatter;
所以,我在这里看到三个有效的单元测试
DateFilter 模块应该导出一个函数
日期过滤器应使用传递的日期值初始化时刻
日期过滤器应该在传递了 dateFormat 的那一刻调用 format 方法
DateFilter.test.js
import moment from 'moment';
import DateFilter from './DateFilter';
describe('DateFilter', () =>
it('should exist', () =>
expect(DateFilter).toBeDefined();
expect(typeof DateFilter).toBe('function');
);
it('should moment.format with the dateValue and dateFormat passed.', () =>
// Here I get lost in how to spyOn moment function and the .format function
const mockDateFormat = `dateFormat-$Math.random()`;
const mockDate = `mockDate-$Math.random()`;
jest.mock('moment', () =>
return format: jest.fn()
);
// expect moment to have been called with mockDate
// expect moment(mockDate) to have been called with mockDateFormat
);
);
【问题讨论】:
【参考方案1】:不确定你想测试多少细节,但我猜这个秘密是对 momentjs 的一个很好的模拟。由于您只想测试您的 dateFormatter,您可以执行以下操作:
首先我们将 mock 设置为 momentjs:
jest.mock('moment', () =>
const momentMock = format: jest.fn()
return jest.fn(() => momentMock);
);
如果您尝试将对象传递给jest.fn
而不是声明 const,您可能会收到未调用该函数的错误,那是因为我们将在每次调用 moment 时生成不同的 mock,而不是使用相同的 mock对于所有moment
调用。
这是一个非常简单的,你可以做一个更详细的时刻模拟,但我认为不值得付出努力,因为你的功能很简单。
然后,我认为您已经分离了单元测试,您可以将它们放在一个中,但有时单独断言函数链会更好。
it('calls moment with the dateValue passed.', () =>
const mockDateFormat = `dateFormat-$Math.random()`;
const mockDate = `mockDate-$Math.random()`;
dateFormatter(mockDate, mockDateFormat);
expect(moment).toHaveBeenCalledWith(mockDate)
);
it('calls format with the dateFormat passed.', () =>
const mockDateFormat = `dateFormat-$Math.random()`;
const mockDate = `mockDate-$Math.random()`;
dateFormatter(mockDate, mockDateFormat);
expect(moment(mockDate).format).toHaveBeenCalledWith(mockDateFormat)
);
免责声明:在第二个测试中,您是否期望 moment(), moment(mockDate) or moment('Whatever')
并不重要,因为您总是模拟相同的东西,您将收到相同的 format
模拟返回。
如果你想要更复杂的东西,你需要创建一个fixture,将momentjs被调用的日期映射到一个包含模拟函数的新对象。但我相信这更麻烦,实际上你最好只测试那个时刻已经被调用并且格式已经被调用。否则,您将在很大程度上测试 3rd 方库的工作方式。
希望这能给你一些指导
【讨论】:
以上是关于模拟 es6 模块返回工厂函数(moment.js)的主要内容,如果未能解决你的问题,请参考以下文章
TypeScript + moment.js:错误 TS2307:找不到模块'moment'