【问题标题】:How do I reset the redux-test-utils store between tests如何在测试之间重置 redux-test-utils 存储
【发布时间】:2018-07-26 13:11:12
【问题描述】:

我有一个订阅者,它根据提供给 pub 事件的参数调度一个操作

// subscriptions.js
import store from '../store';
import { action } from '../actions';
export const subscribeToToggle = () => {
    window.$.subscribe('action/toggle', (_e, isToggleOn) => {

        if (isToggleOn=== true){
            store.dispatch(action());
        }
    });
};

在我的测试文件中,我编写了 2 个测试来测试仅在提供 true 时才发送操作。

// subscriptions.test.js
import { subscribeToToggle } from './subscriptions';
import jQuery from 'jquery';
import { actionTypes } from '../constants';
import store from '../store';
jest.mock('../store');

beforeEach(() => {
    window.$ = jQuery;
    window.$.unsubscribe('action/toggle');

});

test('Action not sent when false', () => {

    subscribeToToggleOpen();
    window.$.publish('action/toggle', false);

    expect(store.getActions().length).toBe(0);
});

test('Action sent when true', () => {

    subscribeToToggleOpen();
    window.$.publish('action/toggle', true);

    expect(store.getActions().length).toBe(1);
    expect(store.getActions()[0].type).toBe(actionTypes.ACTION);
});

我有以下使用 redux-test-utils 模拟的商店

import { createMockStore } from 'redux-test-utils';
let store = null;
store = createMockStore('');
export default store;

我面临的问题是,我的测试只有在错误测试首先出现时才能通过。如果它们是“假时未发送的动作”测试失败的另一种方式,因为它看到“真时发送的动作”测试提供的动作。

我有什么办法可以使用 beforeEach 方法来重置模拟的商店对象?

【问题讨论】:

    标签: javascript redux jestjs


    【解决方案1】:

    在这种情况下,问题在于您的商店本质上是一个单例。当您尝试执行此类操作时,这可能会产生问题,并且通常是一种反模式。

    与其导出存储对象,不如导出一个getStore() 函数,该函数可以被调用来获取存储。在这种情况下,您可以这样做:

    getStore().dispatch(action());
    

    在其中,您可以使用其他辅助函数来替换它返回的商店。该文件可能如下所示:

    import { createMockStore } from 'redux-test-utils';
    let store = createMockStore('');
    
    export default () => store;
    

    然后,您可以在其中添加另一个可能是 resetStore 的非默认导出:

    export const resetStore = () => store = createMockStore('');
    

    在技术上它仍然是一个单例,但它现在是一个你可以控制的单例。

    然后,在您的测试中的beforeEach() 中,只需调用resetStore()

    import { resetStore } from '../store';
    
    beforeEach(() => {
      resetStore();
    });
    

    这还需要您更新真实代码以直接使用getStore() 而不是store,但从长远来看,这可能是一个有益的改变。


    完整更新版本:

    // subscriptions.js
    import getStore from '../store';
    import { action } from '../actions';
    export const subscribeToToggle = () => {
        window.$.subscribe('action/toggle', (_e, isToggleOn) => {
    
            if (isToggleOn=== true){
                getStore().dispatch(action());
            }
        });
    };
    

    // subscriptions.test.js
    import { subscribeToToggle } from './subscriptions';
    import jQuery from 'jquery';
    import { actionTypes } from '../constants';
    import getStore, { resetStore } from '../store';
    jest.mock('../store');
    
    beforeEach(() => {
        window.$ = jQuery;
        window.$.unsubscribe('action/toggle');
        resetStore();
    });
    
    test('Action not sent when false', () => {
        subscribeToToggleOpen();
        window.$.publish('action/toggle', false);
    
        expect(getStore().getActions().length).toBe(0);
    });
    
    test('Action sent when true', () => {
    
        subscribeToToggleOpen();
        window.$.publish('action/toggle', true);
    
        expect(getStore().getActions().length).toBe(1);
        expect(getStore().getActions()[0].type).toBe(actionTypes.ACTION);
    });
    

    import { createMockStore } from 'redux-test-utils';
    let store;
    
    export const resetStore = () => { store = createMockStore(''); }
    
    resetStore(); // init the store, call function to keep DRY
    
    export default () => store;
    

    除此之外,另一种方法是拥有一个全局 reducer,它可以将 store 的状态重置为默认值,但这会更麻烦,我认为通常不适合编写单元测试。

    【讨论】:

    • 谢谢,我想改变我的商店的性质,以便我可以对它进行单元测试它会感觉很糟糕,并且在正在运行的应用程序(而不是测试)的上下文中,我希望我的商店成为单身人士。所以这绝对是正确的答案,但现在我要让我的测试保持相同的顺序
    • 从长远来看,即使没有单元测试,您也可能会发现您正在使用的模式存在问题。返回一些你不可能改变的东西通常不是一个好主意。您仍然可以将其保留为单例,但通过函数将其返回。然后,如果您需要进行更改,重构就会变得不那么痛苦。
    猜你喜欢
    • 2019-05-02
    • 2020-09-05
    • 2022-01-04
    • 2019-04-17
    • 2021-04-03
    • 2021-02-17
    • 2017-04-26
    • 2018-11-09
    • 2019-10-24
    相关资源
    最近更新 更多