私がテストしようとしているコードのいくつかは、例えばを使用してプラットフォームを検出します:
import { Platform } from 'react-native';
...
if (Platform.OS === 'Android') {
...
} else {
...
}
これをJestや他の何かでモックする賢明な方法はあるので、1回のテスト実行で両方のブランチをテストできますか?
それとも、それを切り離してプラットフォームをコンテキスト変数などに入れるスマートな方法ですか?テストを容易にするためにコードを再構築することは常に感じられますが、それはごまかしのようなものです。
これは私のために働いた(Jest 21.2.1、Enzyme 3.2.0):
jest.mock('Platform', () => {
const Platform = require.requireActual('Platform');
Platform.OS = 'Android';
return Platform;
});
テストの先頭、または a beforeAll
などに配置します。
プラットフォームをモック設定する方法は、テストで直接設定するだけでした。
it('should only run for Android', () => {
Platform.OS = 'Android'; // or 'ios'
// For my use case this module was failing on iOS
NativeModules.MyAndroidOnlyModule = {
fetch: jest.fn(
(url, event) => Promise.resolve(JSON.stringify(event.body))
),
};
return myParentFunction().then(() => {
expect(NativeModules.MyAndroidOnlyModule.fetch.mock.calls.length).toBe(1);
expect(fetch.mock.calls.length).toBe(0);
});
});
これにより、テスト中にAndroidでのみ実行されるようにプラットフォームがセットアップされ、関数が特定の関数のみを呼び出していることが確認されます。プラットフォーム依存コンパイルでラップされた関数は次のようになりました:
export default function myParentFunction() {
if (Platform.OS === 'ios') {
return fetch();
}
return NativeModules.MyAndroidOnlyModule.fetch();
}
プラットフォームにiOSを設定し、もう1つをAndroidに設定するという2つの異なるテストを作成することをお勧めします。理想的には、機能には1つの責任のみを持たせる必要があります。最初のテストを実行し、プラットフォームを動的に設定し、テスト番号2をすべて1つの関数で実行します。
異なるOSをモックしたい場合、他の答えは機能しません同じテストスイート内および1回のテスト実行で、別の方法があります。コードでPlatform.OS
を直接使用する代わりに、どこかにヘルパー関数を定義して使用します。
export function getOS() {
return Platform.OS;
}
この関数canをテストでモックすることができます。
import * as helpers from './helpers';
// ...
it('does something on Android', () => {
jest.spyOn(helpers, 'getOS').mockImplementation(() => 'Android');
// ...
}
it('does something else on iOS', () => {
jest.spyOn(helpers, 'getOS').mockImplementation(() => 'ios');
// ...
}
このアイデアの功績は このGitHubの問題のコメント にあります。
これが必要なモックです:
const mockPlatform = OS => {
jest.resetModules();
jest.doMock("Platform", () => ({ OS, select: objs => objs[OS] }));
};
それを使用すると、次のことができます。
it("my test on Android", () => {
mockPlatform("Android");
});
it("my test on iOS", () => {
mockPlatform("ios");
});
そうすれば、両方のプラットフォームのテストを行うことができます
「インポート」メソッドの問題かもしれません。これをチェックしてください:
const isAndroid = require('app/helpers/is_Android');
//import isAndroid from 'app/helpers/is_Android'
「インポート」では、これは機能しません。「必須」を使用する必要があります。
beforeEach(() => {
jest.resetModules();
});
it("should be true when Android", () => {
jest.mock('Platform', () => {
return { OS: 'Android' };
});
expect(isAndroid).toBe(true);
});
このgithubの問題のソリューションを使用しています https://github.com/facebook/jest/issues/1370#issuecomment-352597475
Jest構成をpackage.json
から別のファイルに移動しました。これまでのところ、以下を含むすべてがうまく機能しているようです:a)適切なファイルがプラットフォームに従ってインポートされます。たとえば、iosの場合:.ios.tsx、.native.tsx、.tsx b)PLATFORM.IOSは、test-iosの実行時にtrueを返します。何もモックする必要はありません
// package.json
"scripts": {
"test": "cross-env NODE_ENV=test jest --config config/jest.desktop.json",
"test-ios": "cross-env NODE_ENV=test jest --config config/jest.ios.json",
"test-Android": "cross-env NODE_ENV=test jest --config config/jest.Android.json"
}
// config/jest.web.json
{
...
}
// config/jest.ios.json
{
...
"preset": "react-native",
"haste": {
"defaultPlatform": "ios",
"platforms": [
"Android",
"ios",
"native"
],
"providesModuleNodeModules": [
"react-native"
]
},
}
// config/jest.Android.json
{
...
"preset": "react-native",
"haste": {
"defaultPlatform": "Android",
"platforms": [
"Android",
"ios",
"native"
],
"providesModuleNodeModules": [
"react-native"
]
},
}
jest.doMock および jest.resetModules を使用します
jest.resetModules()
jest.doMock('react-native', () => ({ Platform: { OS: 'Android' }}))
React-Native
から好きなものを次のようにモックできます。
describe('notifications actions tests', () => {
let Platform;
beforeEach(() => {
jest.mock('react-native', () => ({
Platform: {
...
}));
Platform = require('react-native').Platform; // incase u would like to refer to Platform in your tests
});
import React from "react";
import renderer from "react-test-renderer";
import SmartText from "../SmartText";
describe("markdown smart text component", () => {
beforeEach(() => {
jest.resetModules();
});
it("renders with props on ios", () => {
jest.mock("Platform", () => {
return { OS: "ios" };
});
expect(
renderer.create(<SmartText title="code ios" code />).toJSON()
).toMatchSnapshot();
});
it("renders with props on Android", () => {
jest.mock("Platform", () => {
return { OS: "Android" };
});
expect(
renderer.create(<SmartText title="code Android" code />).toJSON()
).toMatchSnapshot();
});
});