测试自定义钩子:不变违规:找不到 react-redux 上下文值;请确保组件包装在 <Provider>
Posted
技术标签:
【中文标题】测试自定义钩子:不变违规:找不到 react-redux 上下文值;请确保组件包装在 <Provider>【英文标题】:Testing custom hook: Invariant Violation: could not find react-redux context value; please ensure the component is wrapped in a <Provider> 【发布时间】:2020-04-16 00:24:19 【问题描述】:我有一个想要测试的自定义钩子。它接收一个 redux store 调度函数并返回一个函数。为了得到我想要做的结果:
const result = renderHook(() => useSaveAuthenticationDataToStorages(useDispatch()));
但是,我收到一个错误:
Invariant Violation:找不到 react-redux 上下文值;请确保组件被包裹在一个
这是因为useDispatch
并且没有连接商店。但是,我这里没有任何组件可以与提供程序一起包装。我只需要测试挂钩,它只是将数据保存到商店。
我该如何解决?
【问题讨论】:
【参考方案1】:react hooks 测试库docs 对此进行了更深入的研究。但是,我们本质上缺少的是可以通过创建包装器获得的提供程序。首先我们声明一个组件作为我们的提供者:
import Provider from 'react-redux'
const ReduxProvider = ( children, reduxStore ) => (
<Provider store=reduxStore>children</Provider>
)
那么在我们的测试中我们调用
test("...", () =>
const store = configureStore();
const wrapper = ( children ) => (
<ReduxProvider reduxStore=store>children</ReduxProvider>
);
const result = renderHook(() =>
useSaveAuthenticationDataToStorages(useDispatch());
, wrapper );
// ... Rest of the logic
);
【讨论】:
请注意,如果你把这个ReduxProvider
放在它自己的文件中(就像我一样),你需要导入 react 才能让它工作 import React from 'react';
configureStore()
是什么?【参考方案2】:
这可能是一个较晚的答案,但您也可以在测试中使用它
jest.mock('react-redux', () =>
const ActualReactRedux = jest.requireActual('react-redux');
return
...ActualReactRedux,
useSelector: jest.fn().mockImplementation(() =>
return mockState;
),
;
);
【讨论】:
我不确定我是否理解这一点。我将此添加到测试中,但我仍然看到有关缺少<Provider>
的错误。你能扩展这个答案吗?
考虑提供完整的答案。
我收到一个错误TypeError: require.requireActual is not a function
,你知道为什么吗?
@Sachihiro 你需要jest.requireActual
而不是require.requireActual
似乎可行,但您将无法在测试用例中更新 mockState?【参考方案3】:
此问题与您的测试文件有关。您必须在测试文件中声明 provider 和 store。
通过以下代码更新或替换您的app.test.tsx
注意:如果您还没有安装redux-mock-store
,请不要忘记安装。
import React from 'react';
import render from '@testing-library/react';
import App from './App';
import Provider from 'react-redux';
import configureStore from 'redux-mock-store';
describe('With React Testing Library', () =>
const initialState = output: 10 ;
const mockStore = configureStore();
let store;
it('Shows "Hello world!"', () =>
store = mockStore(initialState);
const getByText = render(
<Provider store=store>
<App />
</Provider>
);
expect(getByText('Hello World!')).not.toBeNull();
);
);
我在搜索 1 小时后得到了这个解决方案。 非常感谢OSTE
原解决方案:Github issues/8145 and solution link
使用此解决方案,如果您遇到 TypeError: window.matchMedia is not a function 之类的错误,请通过此方式解决。将这些行添加到您的 setupTests.ts
文件中。原解决方案链接***.com/a/64872224/5404861
global.matchMedia = global.matchMedia || function ()
return
addListener: jest.fn(),
removeListener: jest.fn(),
;
;
【讨论】:
【参考方案4】:我认为您可以像这样创建test-utils.[j|t]s(?x)
或whatever you set the name of the file to
:
https://github.com/hafidzamr/nextjs-ts-redux-toolkit-quickstart/blob/main/__tests__/test-utils.tsx
//root(or wherever your the file)/test-utils.tsx
import React from 'react';
import render, RenderOptions from '@testing-library/react';
import Provider from 'react-redux';
// Import your store
import store from '@/store';
const Wrapper: React.FC = ( children ) => <Provider store=store>children</Provider>;
const customRender = (ui: React.ReactElement, options?: Omit<RenderOptions, 'wrapper'>) => render(ui, wrapper: Wrapper, ...options );
// re-export everything
export * from '@testing-library/react';
// override render method
export customRender as render ;
像这样使用它:
https://github.com/hafidzamr/nextjs-ts-redux-toolkit-quickstart/blob/main/__tests__/pages/index.test.tsx
//__tests__/pages/index.test.tsx
import React from 'react';
import render, screen from '../test-utils';
import Home from '@/pages/index';
describe('Home Pages', () =>
test('Should be render', () =>
render(<Home />);
const getAText = screen.getByTestId('welcome');
expect(getAText).toBeInTheDocument();
);
);
为我工作。
screenshot work
顺便说一句,如果您将test-utils.[j|t]s(?x)
或whatever you set the name file
放在目录__test__
上,不要忘记在jest.config.js
上忽略它。
//jest.config.js
testPathIgnorePatterns: ['<rootDir>/node_modules/', '<rootDir>/.next/', '<rootDir>/__tests__/test-utils.tsx'],
回购:https://github.com/hafidzamr/nextjs-ts-redux-toolkit-quickstart
【讨论】:
以上是关于测试自定义钩子:不变违规:找不到 react-redux 上下文值;请确保组件包装在 <Provider>的主要内容,如果未能解决你的问题,请参考以下文章
不变违规:TurboModuleRegistry.getEnforcing(...): 'NativeReanimated' 找不到
不变违规:requireNativeComponent:在 UIManager 中找不到“AIRMap”。没有修复?
不变违规:requireNativeComponent:在反应原生的 UIManager 中找不到“FastImageView”
JestJS -> 不变违规:在“连接(投资组合)”的上下文或道具中找不到“商店”
next.js + GraphQL:“不变违规:在上下文中找不到“客户端”或作为选项传入......”
不变违规:requireNativeComponent:在 UIManager 中找不到“RNCSafeAreaView”。在 expo 应用程序中反应原生