模拟es6模块返回工厂功能(moment.js)

Mat*_*ley 5 javascript unit-testing vue.js jestjs vuejs2

警告:我是Jest的新手所以熊.

我试图使用名为DateFilter的Jest测试Vue2.js过滤器.此过滤器只是将日期格式应用于传递给它的日期.

DateFilter.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;
Run Code Online (Sandbox Code Playgroud)

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

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

  2. 日期过滤器应该在传递dateValue的情况下初始化时刻

  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
    });
});
Run Code Online (Sandbox Code Playgroud)

Sir*_*ple 4

不确定你想测试多少细节,但我猜这个秘密是对 momentjs 的一个很好的模拟。由于您只想测试 dateFormatter,因此您可以执行以下操作:

首先我们将模拟设置为 momentjs:

jest.mock('moment', () => {
    const momentMock = { format: jest.fn() }

    return jest.fn(() => momentMock);
});
Run Code Online (Sandbox Code Playgroud)

如果您不声明 const,而是尝试将对象传递给jest.fn您,则可能会收到未调用该函数的错误,那是因为每次调用 moment 时我们都会生成不同的模拟,而不是为所有调用提供相同的模拟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)
});
Run Code Online (Sandbox Code Playgroud)

免责声明:在第二个测试中,您是否期望并不重要moment(), moment(mockDate) or moment('Whatever'),因为您总是模拟相同的事物,您将收到相同的format模拟。

如果您想要更复杂的东西,您将需要创建一个固定装置,在其中将调用 momentjs 的日期映射到包含模拟函数的新对象。但我相信这更麻烦,实际上最好只测试那个时刻已经被调用以及那个格式已经被调用。否则,您正在测试第三方库的工作方式。

希望这能给您一些指导