模拟moment.js用道具和酶反应道具

时间:2019-09-17 17:05:20

标签: reactjs mocking jestjs enzyme

说我有一个子组件,该子组件需要两个矩对象作为道具,例如:

import React from 'react';
import PropTypes from 'prop-types';
import moment from 'moment';

class ChildComponent extends React.Component {
    constructor(props) {
        super(props);
    }

    startAndEndDateOnSameDay() {
        return this.props.startDate.isSame(this.props.endDate, 'date')
    }

    render() {
        let formattedDate;
        if(this.startAndEndDateOnSameDay()) {
            formattedDate = this.props.startDate.format();
        }
        else {
            formattedDate = this.props.endDate.fromNow();
        }

        return (
            <div>{formattedDate}</div>
        );
    }
}

ChildComponent.propTypes = {
    startDate: PropTypes.instanceOf(moment).isRequired,
    endDate: PropTypes.instanceOf(moment).isRequired
}

export default ChildComponent;

以及一个将两个矩对象向下传递到子组件的父组件,例如:

import React from 'react';
import PropTypes from 'prop-types';
import moment from 'moment';
import ChildComponent from './ChildComponent';

class ParentComponent extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            startDate: moment(),
            endDate: moment()
        };
    }

    render() {
        return (
            <ChildComponent startDate={this.state.startDate} endDate={this.state.endDate}/>
        );
    }
}

export default ParentComponent;

我正在尝试通过以下方式来测试这些成分:

import React from 'react';
import { shallow } from 'enzyme';
import ParentComponent from '../components/ParentComponent';

describe('<ParentComponent />', () => {
    let wrapper;

    beforeAll(() => {
        wrapper = shallow(<ParentComponent/>);
    });

    it('should render the component correctly', () => {
        expect(wrapper).toMatchSnapshot();
    });
});

import React from 'react';
import { shallow } from 'enzyme';
import ChildComponent from '../components/ChildComponent';
import moment from 'moment';

describe('<ChildComponent />', () => {
    let wrapper;

    beforeAll(() => {
        wrapper = shallow(<ChildComponent startDate={moment()} endDate={moment()}/>);
    });

    it('should render the component correctly', () => {
        expect(wrapper).toMatchSnapshot();
    });

    describe('when the the start date and end date are on the same day', () => {
        it('should print a the formatted start date', () => {
            expect(wrapper.text()).toEqual('mock format here');
        });
    });

    describe('when the start and end date are not on the same day', () => {
        it('should print the the end date from now', () => {
            expect(wrapper.text()).toEqual('mock from now here');
        });
    });
});

如何模拟moment.js库函数以使测试正常工作?

我试图在__mocks__文件夹中创建一个手动模拟文件,该文件将模拟两个测试套件的矩量库的功能。我遇到的当前问题:

  1. 如何从模拟文件中模拟moment()构造函数以始终返回相同的日期,以便快照测试始终通过?
  2. 如何模拟.isSame().format().fromNow()函数以始终返回相同的值而不管当前时间如何?

到目前为止,我拥有跟随测试文件,该文件破坏了所有测试。我正在关注文档here

const moment = require('moment');

function isSame() {
  return true;
}

function fromNow() {
  return 'Tomorrow at 12:00 pm'
}

function format() {
  return 'Sept 16th 19';
}

exports.isSame = isSame;
exports.fromNow = fromNow;
exports.format = format;

使用该文件时,我的组件中出现错误,提示未定义startDate和endDate。

2 个答案:

答案 0 :(得分:1)

我最终通过在 mocks 文件夹中创建一个手动模拟来解决了这个问题。关键是当下使用moment.fn导出它的原型。

import fixtures from '../__fixtures__/moment';

const moment = require.requireActual('moment');

// By default, the isSame function will always return true
let isSame = true;

moment.fn.isSame = () => isSame;
moment.fn.calendar = () => fixtures.CALENDAR;
moment.fn.fromNow = () => fixtures.FROM_NOW;

// Since format is often called with a variety of format strings, we need to
// differentiate how we are calling the function
moment.fn.format = (format) => {
    switch (format) {
    case 'MMM Do YY':
        return fixtures.DATE;
    case 'H:mm a':
        return fixtures.TIME;
    case 'MMM Do YY H:mm a':
        return fixtures.DATETIME;
    default:
        return Error('Unsupported format in moment mock. Add case to __mocks__/moment.js');
    }
};
moment.duration.fn.humanize = () => fixtures.DURATION;

// This function is added to moment's prototype in order for our tests to
// change moment's isSame behaviour
moment.fn.__isSame = (value) => { isSame = value; };

// This resets the isSame behaviour back to default
moment.fn.__reset = () => {
    moment.fn.isSame = () => true;
};

export default moment;

Jest在运行测试时会自动加载此文件,然后我可以像以下测试我的组件了:

it('renders a moment duration', () => {
    expect(wrapper.text()).toEqual(fixtures.DURATION);
});

如果我需要更改.isSame函数的行为,可以使用以下方法进行修改:

import moment from 'moment';

beforeAll(() => {
    moment.fn.__isSame(false);
});

答案 1 :(得分:0)

如果您正在使用JEST进行测试,我可以推荐您https://github.com/hustcc/jest-date-mock,然后可以使用

模拟当前日期
advanceTo(new Date(2018, 5, 27, 0, 0, 0));

要测试的最佳实践是模拟固定日期并与结果进行比较