高次コンポーネントを使用した React Native Jest テストのセットアップ
25464 ワード
あなたの React Native アプリが私たちのアプリのようなものなら、画面と画面コンポーネントをラップする、ラッパーの上にラッパーがあります.いくつかの例は次のとおりです.
SafeAreaProvider - デバイスの安全な領域にのみアクセスしていることを確認するため
ThemeProvider - Styled Components のようなものを使用して、アプリ全体にテーマ コンテキストを提供していたとします
Redux - アプリ全体の状態を管理するため
これにより、単体テストと統合テストを作成する際に注意が必要になります.コンポーネントが、1 つ以上の高次コンポーネント (HoC) によって提供されるものに誤って依存する可能性があるためです.
Jest テストのセットアップを簡素化するために、必要な HoC をテストごとに簡単に利用できるようにするヘルパー関数をいくつか作成しました.物事を単純化するということは、開発時間を短縮しながら、より多くのテストを作成する障壁を下げることを意味するため、これは大きなメリットです. 🎉
Typescript でそれを行う方法の例を次に示します.私たちが使用する外部パッケージは、Redux Toolkit、Styled Components、および React Native Safe Area Context です.
ここでは非常に多くのことが起こっているので、それを分解しましょう.しかし、最初に、次のことについて話し合う必要があります...
これらのヘルパー メソッドを実際にどのように使用したいかを最初に理解する方が簡単だといつも思います.したがって、これらのヘルパーをテストに統合する方法の例を追加しました.これは React’s Test Renderer を使用することに注意してください.これは、たとえば、予想される要素の存在をチェックするのに役立ちます.
特定のユーザー アクションが特定の期待をもたらすかどうかをテストしたい場合は、React Testing Library (React のテスト レンダラーの上にある) が最適です.
ヘルパー関数が実際にどのように使用されるかを理解したので、ヘルパー ファイルの設定方法に戻りましょう.
このファイルの中心にあるのは
この関数は、テストする要素/コンポーネントと、オプションの
Redux の状態をモックするときは、テスト用の Redux の状態がいくつかの初期値で設定されていることを確認する必要があります.これを行うために、さまざまな Redux Toolkit スライスからすべての初期状態を抽出し、それを 1 つのオブジェクトに結合し、それを
以上です!これにより、React Native のテスト作業が少し楽になることを願っています. 😄 何か提案や改善点がありましたら、お知らせください.テスト ゲームの改善に常に力を入れています.私は https://bionicjulia.com にいます.
SafeAreaProvider - デバイスの安全な領域にのみアクセスしていることを確認するため
ThemeProvider - Styled Components のようなものを使用して、アプリ全体にテーマ コンテキストを提供していたとします
Redux - アプリ全体の状態を管理するため
これにより、単体テストと統合テストを作成する際に注意が必要になります.コンポーネントが、1 つ以上の高次コンポーネント (HoC) によって提供されるものに誤って依存する可能性があるためです.
Jest テストのセットアップを簡素化するために、必要な HoC をテストごとに簡単に利用できるようにするヘルパー関数をいくつか作成しました.物事を単純化するということは、開発時間を短縮しながら、より多くのテストを作成する障壁を下げることを意味するため、これは大きなメリットです. 🎉
Typescript でそれを行う方法の例を次に示します.私たちが使用する外部パッケージは、Redux Toolkit、Styled Components、および React Native Safe Area Context です.
// testHelpers.tsx
import * as React from 'react'
import { getDefaultMiddleware } from '@reduxjs/toolkit'
import lodash from 'lodash'
import { SafeAreaProvider } from 'react-native-safe-area-context'
import { Provider as ReduxProvider } from 'react-redux'
import renderer, { ReactTestInstance } from 'react-test-renderer'
import createMockStore from 'redux-mock-store'
import { ThemeProvider } from 'styled-components/native'
import { TRootState } from '@app/core/state/root'
import { initialState } from '@app/core/state/mockedInitialState'
import { theme } from '@app/themes'
type DeepPartial<T> = {
[P in keyof T]?: DeepPartial<T[P]>
}
type TConfig = {
mockRedux?: boolean
mockSafeAreaProvider?: boolean
mockTheme?: boolean
state?: DeepPartial<TRootState>
}
const initialMetrics = {
frame: { height: 0, width: 0, x: 0, y: 0 },
insets: { bottom: 0, left: 0, right: 0, top: 0 },
}
export function createMockedElement(element: React.ReactElement, config?: TConfig) {
let mockedElement = element
if (config?.mockRedux !== false) {
const middlewares = getDefaultMiddleware()
const mockStore = createMockStore(middlewares)
const state = lodash.merge(initialState, config?.state)
const store = mockStore(state)
mockedElement = <ReduxProvider store={store}>{mockedElement}</ReduxProvider>
}
if (config?.mockTheme !== false) {
mockedElement = <ThemeProvider theme={theme}>{mockedElement}</ThemeProvider>
}
if (config?.mockSafeAreaProvider !== false) {
mockedElement = <SafeAreaProvider initialMetrics={initialMetrics}>{mockedElement}</SafeAreaProvider>
}
return mockedElement
}
export function createReactTestInstance(element: React.ReactElement, config?: TConfig): ReactTestInstance {
return renderer.create(createMockedElement(element, config)).root
}
ここでは非常に多くのことが起こっているので、それを分解しましょう.しかし、最初に、次のことについて話し合う必要があります...
ヘルパー関数の実際の使用方法
これらのヘルパー メソッドを実際にどのように使用したいかを最初に理解する方が簡単だといつも思います.したがって、これらのヘルパーをテストに統合する方法の例を追加しました.これは React’s Test Renderer を使用することに注意してください.これは、たとえば、予想される要素の存在をチェックするのに役立ちます.
import { createReactTestInstance } from './testHelpers'
describe('MyComponent tests', () => {
it('renders correct version for users who shown interest', () => {
const instance = createReactTestInstance(<MyComponent />)
expect(instance.findByProps({ testID: `interested-icon` })).toBeTruthy()
})
it('renders correct version for users who have not shown interest', () => {
const instance = createReactTestInstance(<MyComponent />)
expect(instance.findByProps({ testID: `not-interested-icon` })).toBeTruthy()
})
})
特定のユーザー アクションが特定の期待をもたらすかどうかをテストしたい場合は、React Testing Library (React のテスト レンダラーの上にある) が最適です.
createReactTestInstance
ヘルパーを使用する代わりに、createMockedElement
ヘルパーを利用することができます.例を次に示します.import { fireEvent, render } from '@testing-library/react-native'
import { act } from 'react-test-renderer'
import { createMockedElement } from './testHelpers'
const navigateMock = jest
.mock
// your mock...
()
describe('BackButton tests', () => {
it('navigates to the right screen onPress', async () => {
const mockedElement = createMockedElement(<BackButton previousScreen="PreviousScreenName" />)
const renderAPI = await render(mockedElement)
await act(async () => {
const backButton = renderAPI.getByTestId('button-back-navigation')
await fireEvent.press(backButton)
expect(navigateMock).toHaveBeenCalledWith('PreviousScreenName')
})
})
})
ヘルパー関数が実際にどのように使用されるかを理解したので、ヘルパー ファイルの設定方法に戻りましょう.
ヘルパーファイルの壊れ方
このファイルの中心にあるのは
createMockedElement
関数です.export function createMockedElement(element: React.ReactElement, config?: TConfig) {
let mockedElement = element
if (config?.mockRedux !== false) {
const middlewares = getDefaultMiddleware()
const mockStore = createMockStore(middlewares)
const state = lodash.merge(initialState, config?.state)
const store = mockStore(state)
mockedElement = <ReduxProvider store={store}>{mockedElement}</ReduxProvider>
}
if (config?.mockTheme !== false) {
mockedElement = <ThemeProvider theme={theme}>{mockedElement}</ThemeProvider>
}
if (config?.mockSafeAreaProvider !== false) {
mockedElement = <SafeAreaProvider initialMetrics={initialMetrics}>{mockedElement}</SafeAreaProvider>
}
return mockedElement
}
この関数は、テストする要素/コンポーネントと、オプションの
config
オブジェクトの 2 つの引数を取ります.この構成オブジェクトを使用すると、テスト中にコンポーネントをレンダリングするときに含めるラッパーを指定できます (存在する場合).たとえば、Redux の状態をモックする必要がある場合は、次のようにテストをセットアップできます.it("doesn't open the modal when row is active", async () => {
const mockedState = { show_modal: false }
const config = { state: mockedState }
const mockedElement = createMockedElement(<Row />, config)
const renderAPI = await render(mockedElement)
await act(async () => {
// ... your test expectations
})
})
ThemeProvider
および/または SafeAreaProvider
ラッパーを含める必要がある場合も、同様に同じことができます. TConfig
で定義されているように、これら 2 つのオプションは boolean
の入力を受け取ることに注意してください.Redux 状態の設定について深く掘り下げる
Redux の状態をモックするときは、テスト用の Redux の状態がいくつかの初期値で設定されていることを確認する必要があります.これを行うために、さまざまな Redux Toolkit スライスからすべての初期状態を抽出し、それを 1 つのオブジェクトに結合し、それを
lodash
マージ関数に渡しました (モックされた状態と深くマージされるようにするため).// @app/core/state/mockedInitialState
import { initialStateFeature1 } from '@covid/core/state/feature1.slice'
import { initialStateFeature2 } from '@covid/core/state/feature2.slice'
import { initialStateFeature3 } from '@covid/core/state/feature3.slice'
export const initialState: TRootState = {
feature1: initialStateFeature1,
feature2: initialStateFeature2,
feature3: initialStateFeature3,
}
以上です!これにより、React Native のテスト作業が少し楽になることを願っています. 😄 何か提案や改善点がありましたら、お知らせください.テスト ゲームの改善に常に力を入れています.私は https://bionicjulia.com にいます.
Reference
この問題について(高次コンポーネントを使用した React Native Jest テストのセットアップ), 我々は、より多くの情報をここで見つけました https://dev.to/bionicjulia/setting-up-react-native-jest-tests-with-higher-order-components-mn4テキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol