Javascript 如何在测试之间重置redux测试utils存储

Javascript 如何在测试之间重置redux测试utils存储,javascript,redux,jestjs,Javascript,Redux,Jestjs,我有一个订阅者,它根据提供给发布事件的参数发送一个操作 // subscriptions.js import store from '../store'; import { action } from '../actions'; export const subscribeToToggle = () => { window.$.subscribe('action/toggle', (_e, isToggleOn) => { if (isToggleOn===

我有一个订阅者,它根据提供给发布事件的参数发送一个操作

// 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());
        }
    });
};
在我的测试文件中,我编写了两个测试,测试只有在提供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测试utils的模拟存储

import { createMockStore } from 'redux-test-utils';
let store = null;
store = createMockStore('');
export default store;
我面临的问题是,我的测试只有在错误测试首先出现时才能通过。如果它们与“false时未发送操作”测试相反,则测试失败,因为它看到了“true时发送操作”测试提供的操作


我是否可以使用beforeach方法重置模拟存储对象?

在这种情况下,问题在于您的存储本质上是一个单例。当您尝试这样做时,这可能会产生问题,通常是一种反模式

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

getStore().dispatch(action());
在这里面,您可以使用其他帮助器函数来替换它返回的存储。该文件可能如下所示:

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

export default () => store;
然后,您可以在其中添加另一个
resetStore
作为非默认导出:

export const resetStore = () => store = createMockStore('');
从技术上讲,它仍然是一个单体,但现在它是一个你可以控制的单体

然后,在测试中的
beforeach()
中,只需调用
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.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;