React native 在Jest和React Native中模拟平台检测
我尝试测试的一些代码检测平台,例如:React native 在Jest和React Native中模拟平台检测,react-native,jestjs,React Native,Jestjs,我尝试测试的一些代码检测平台,例如: 从'react native'导入{Platform}; ... 如果(Platform.OS==='android'){ ... }否则{ ... } 有没有一种明智的方法可以用笑话和/或其他东西来模拟这一点,这样我就可以在一次测试运行中测试这两个分支 或者,将其解耦并将平台放入(例如)上下文变量中是一种明智的方法?尽管它总是觉得重新构造代码以使其更易于测试是一种欺骗 您可以从React Native模拟任何您想要的内容,如下所示: descriptio
从'react native'导入{Platform};
...
如果(Platform.OS==='android'){
...
}否则{
...
}
有没有一种明智的方法可以用笑话和/或其他东西来模拟这一点,这样我就可以在一次测试运行中测试这两个分支
或者,将其解耦并将平台放入(例如)上下文变量中是一种明智的方法?尽管它总是觉得重新构造代码以使其更易于测试是一种欺骗 您可以从
React Native
模拟任何您想要的内容,如下所示:
description('notifications actions tests',()=>{
让平台;
在每个之前(()=>{
jest.mock('react-native',()=>({
站台:{
...
}));
Platform=require('react-native')。Platform;//如果您想在测试中引用平台
});
您必须模拟模块并将其导入测试。然后您可以使用模拟实现
将其设置为android
或ios
从“react native”导入reactNative;
jest.mock('react-native',()=>jest.fn();
它('是安卓',()=>{
mockImplementation(()=>({Platform:{OS:'android'}}))
//测试android案例
})
它('是安卓',()=>{
mockImplementation(()=>({Platform:{OS:'io'}}))
//测试ios案例
})
我实现模拟设置平台的方法是直接在测试中设置:
it('应该只为Android运行',()=>{
Platform.OS='android';//或'ios'
//对于我的用例,此模块在iOS上出现故障
NativeModules.MyAndroidOnlyModule={
fetch:jest.fn(
(url,event)=>Promise.resolve(JSON.stringify(event.body))
),
};
返回myParentFunction()。然后(()=>{
expect(NativeModules.MyAndroidOnlyModule.fetch.mock.calls.length).toBe(1);
expect(fetch.mock.calls.length).toBe(0);
});
});
这会将平台设置为在测试期间仅在Android上运行,以确保我的函数仅调用特定函数。包装在平台相关编译中的函数如下所示:
导出默认函数myParentFunction(){
如果(Platform.OS==='ios'){
返回fetch();
}
返回NativeModules.MyAndroidOnlyModule.fetch();
}
我建议只创建两个不同的测试,一个将平台设置为iOS,另一个设置为Android,因为理想情况下,一个函数应该只有一个职责。但是,我相信您可以使用它来运行第一个测试,动态设置平台,并运行第二个测试“一体式”函数。使用和
jest.resetModules()
doMock('react-native',()=>({Platform:{OS:'android'}}))
可以直接为每个测试设置操作系统
test('android',()=>{
Platform.OS='android'
const component=renderer.create().toJSON()
expect(component.toMatchSnapshot())
})
测试('ios',()=>{
Platform.OS='ios'
const component=renderer.create().toJSON()
expect(component.toMatchSnapshot())
})
这对我很有效(Jest 21.2.1,Ezyme 3.2.0):
jest.mock('Platform',()=>{
const Platform=require.requireActual(‘平台’);
Platform.OS='android';
返回平台;
});
将它放在测试的顶部,或者放在示例中。我正在使用这个github问题的解决方案 我将jest配置从
package.json
移动到单独的文件中。
到目前为止,一切似乎都很顺利,包括:
a) 根据平台导入正确的文件。例如,在ios上:.ios.tsx,然后是.native.tsx,然后是.tsx
b) 运行测试IOS时,PLATFORM.IOS返回true,无需模拟任何内容
//package.json
“脚本”:{
“test”:“cross env NODE_env=test jest--config/jest.desktop.json”,
“测试ios”:“跨环境节点_env=test jest--config/jest.ios.json”,
“测试android”:“跨环境节点_env=test jest--config/jest.android.json”
}
//config/jest.web.json
{
...
}
//config/jest.ios.json
{
...
“预设”:“反应本机”,
“匆忙”:{
“defaultPlatform”:“ios”,
“平台”:[
“安卓”,
“ios”,
“本地人”
],
“提供模块解调器”:[
“本地反应”
]
},
}
//config/jest.android.json
{
...
“预设”:“反应本机”,
“匆忙”:{
“defaultPlatform”:“android”,
“平台”:[
“安卓”,
“ios”,
“本地人”
],
“提供模块解调器”:[
“本地反应”
]
},
}
如果您想在同一测试套件和一次测试运行中模拟不同的操作系统,那么其他答案将不起作用,这里有另一种方法。不要直接在代码中使用Platform.OS
,而是在某处定义一个helper函数,并使用它来获取组件中操作系统的引用:
在“helpers.js”中:
导出函数getOS(){
returnplatform.OS;
}
在您的组件中:
import*作为“/helpers”中的助手;
render(){
如果(helpers.getOS()=='android'){//do something}
}
然后可以在测试中模拟此函数,例如
import*作为“/helpers”中的助手;
// ...
它('在Android上做点什么',()=>{
jest.spyOn(helpers,'getOS').mock实现(()=>'android');
// ...
}
它('在iOS上做其他事情',()=>{
jest.spyOn(helpers,'getOS').mock实现(()=>'ios');
// ...
}
这个想法的功劳归于。可能是“导入”方法中的问题,请检查以下内容:
const isAndroid = require('app/helpers/is_android');
//import isAndroid from 'app/helpers/is_android'
使用“导入”将不起作用,需要使用“require”
从“React”导入React;
从“反应测试渲染器”导入渲染器;
从“./SmartText”导入SmartText;
描述(“标记智能文本组件”,()=>{
在每个之前(()=>{
jest.reset模块();
});
它(“在ios上使用道具进行渲染”,()=>{
mock(“平台”,()=>{
返回{OS:“ios”};
beforeEach(() => {
jest.resetModules();
});
it("should be true when Android", () => {
jest.mock('Platform', () => {
return { OS: 'android' };
});
expect(isAndroid).toBe(true);
});
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();
});
});
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");
});
jest.mock('react-native/Libraries/Utilities/Platform', () => ({
OS: 'android', // or 'ios'
select: () => null
}));
import * as ReactNative from "react-native";
export const Platform = {
...ReactNative.Platform,
OS: "ios",
Version: 123,
isTesting: true,
select: objs => objs["ios"]
};
export default Object.setPrototypeOf(
{
Platform
},
ReactNative
);
Platform.OS = 'android'
jest.mock('react-native/Libraries/Utilities/Platform', () => {
const Platform = require.requireActual(
'react-native/Libraries/Utilities/Platform'
)
Platform.OS = 'android'
return Platform
})
Object.defineProperty(Platform, 'OS', { get: jest.fn(() => 'ios') })
const mockedData = 'MOCKED-DATA'
jest.mock('react-native', () => ({
Platform: {
select: jest.fn(() => {
return { mockedData } // Your Mocked Value
}),
}
}));
jest.mock('Platform', () => ({
OS: 'android', // or 'ios'
select: () => 'mocked-value'
}));