【问题标题】:Mocking es6 module returning factory function (moment.js)模拟 es6 模块返回工厂函数(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;

所以,我在这里看到三个有效的单元测试

  1. DateFilter 模块应该导出一个函数

  2. 日期过滤器应使用传递的日期值初始化时刻

  3. 日期过滤器应该在传递了 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
    });
});

【问题讨论】:

    标签: javascript unit-testing vue.js vuejs2 jestjs


    【解决方案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 方库的工作方式。

    希望这能给你一些指导

    【讨论】:

      猜你喜欢
      • 2014-01-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-11-07
      • 1970-01-01
      • 2020-01-31
      • 2016-11-01
      相关资源
      最近更新 更多