useContextフックに依存するreactコンポーネントをテストするには?
2023-08-05 04:55:07
質問
あるコンポーネントで
useContext
を使用し、その出力はコンテキストの値に依存します。簡単な例です。
import React, { useContext } from 'react';
const MyComponent = () => {
const name = useContext(NameContext);
return <div>{name}</div>;
};
reactとjestのスナップショットから浅いレンダラでこのコンポーネントをテストするとき。の値を変更するにはどうしたらよいでしょうか?
NameContext
?
どのように解決するのですか?
一般的に、フックを使ってもテスト戦略はあまり変わらないはずです。 ここでのより大きな問題は、実際にはフックではなく、物事を少し複雑にしているコンテキストの使用なのです。
これを動作させる方法はいくつもありますが、私が見つけた唯一のアプローチは
'react-test-renderer/shallow'
で動作する唯一の方法は、モックフックを注入することです。
import ShallowRenderer from 'react-test-renderer/shallow';
let realUseContext;
let useContextMock;
// Setup mock
beforeEach(() => {
realUseContext = React.useContext;
useContextMock = React.useContext = jest.fn();
});
// Cleanup mock
afterEach(() => {
React.useContext = realUseContext;
});
test("mock hook", () => {
useContextMock.mockReturnValue("Test Value");
const element = new ShallowRenderer().render(
<MyComponent />
);
expect(element.props.children).toBe('Test Value');
});
しかし、これは少し汚く、実装に特有なので、シャローレンダラーの使用について妥協できるのであれば、他にもいくつかの選択肢があります。
非シャロー レンダー
シャローレンダリングでない場合は、コンポーネントをコンテキストプロバイダでラップするだけで、必要な値を注入できます。
import TestRenderer from 'react-test-renderer';
test("non-shallow render", () => {
const element = new TestRenderer.create(
<NameContext.Provider value="Provided Value">
<MyComponent />
</NameContext.Provider>
);
expect(element.root.findByType("div").children).toEqual(['Provided Value']);
});
(免責事項:この は が動作するはずなのですが、テストするとエラーになるので、私の設定の問題だと思います)
Enzyme と Dive を使用したシャロー レンダー
Skyboyer さんのコメントにあるように、Enzyme の浅いレンダリングでは
.dive
をサポートしており、浅くレンダリングされたコンポーネントの一部を深くレンダリングすることができます。
import { shallow } from "./enzyme";
test("enzyme dive", () => {
const TestComponent = () => (
<NameContext.Provider value="Provided Value">
<MyComponent />
</NameContext.Provider>
);
const element = shallow(<TestComponent />);
expect(element.find(MyComponent).dive().text()).toBe("Provided Value");
});
ReactDOMを使用する
最後に
フックFAQ
でフックをテストする例があります。
ReactDOM
でフックをテストする例がありますが、これも同様に動作します。 当然ながら
ReactDOM
を使用すると、これも浅いレンダーではなく深いレンダーであることを意味します。
let container;
beforeEach(() => {
container = document.createElement('div');
document.body.appendChild(container);
});
afterEach(() => {
document.body.removeChild(container);
container = null;
});
test("with ReactDOM", () => {
act(() => {
ReactDOM.render((
<NameContext.Provider value="Provided Value">
<MyComponent />
</NameContext.Provider>
), container);
});
expect(container.textContent).toBe("Provided Value");
});
関連
-
[解決済み] テスト
-
[解決済み] error 'document' is not defined : eslint / React
-
[解決済み] バベルエラーです。JSX値は、式または引用されたJSXテキストのいずれかである必要があります。
-
[解決済み] Angular 2の*ngForのReactでの同等品
-
[解決済み] ReactJS で inst.render が関数でないエラーが発生する
-
[解決済み] 拡張子.tsと.tsxの違いは何ですか?どちらもreactのタイプスクリプトファイルの拡張子として使用されます。では、どこで使うべきなのでしょうか?
-
[解決済み] setStateを呼び出さずにReactコンポーネントを強制的に再レンダリングすることは可能ですか?
-
[解決済み] Reactコンポーネント外でのクリックを検出する
-
[解決済み] useEffect React Hook使用時の依存性欠如の警告を修正する方法
-
[解決済み] react-redux hooksを使用してコンポーネントをテストするには?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み】React - 式は1つの親要素を持つ必要がありますか?
-
[解決済み】<Router>の外側で<Link>を使用してはならない
-
[解決済み】Reactを使用したMapBoxのCSSが欠落している件
-
[解決済み] react-router-domを使用する際に「Function components cannot be given refs」を回避するにはどうすればよいですか?
-
[解決済み] React + TypeScript のエラーです。この呼び出しにマッチするオーバーロードがありません
-
[解決済み] componentWillReceiveProps は名称が変更されました。
-
[解決済み] プロップ `history` は `Router` で必須とマークされているが、その値は `undefined` である。
-
[解決済み] 矢印本体を囲む予期せぬブロックステートメント
-
[解決済み] Cross-envでyarnの実行時にenv変数が変更されない。
-
[解決済み] AxiosにCORSの問題が発生