gpt4 book ai didi

typescript - 如何在 React Native 中使用 TypeScript 模拟 React Navigation 的导航 Prop 以进行单元测试?

转载 作者:搜寻专家 更新时间:2023-10-30 20:33:05 27 4
gpt4 key购买 nike

我正在使用 TypeScript 构建一个 React Native 应用程序。对于我的导航,我使用 React Navigation,对于我的单元测试,我使用 Jest 和 Enzyme。

这是我的其中一个屏幕 (LoadingScreen.tsx) 的(精简)代码:

import styles from "./styles";
import React, { Component } from "react";
import { Text, View } from "react-native";
import { NavigationScreenProps } from "react-navigation";

// Is this correct?
export class LoadingScreen extends Component<NavigationScreenProps> {
// Or should I've done:
// export interface Props {
// navigation: NavigationScreenProp<any, any>;
// }

// export class LoadingScreen extends Component<Props> {
componentDidMount = () => {
this.props.navigation.navigate("LoginScreen");
};

render() {
return (
<View style={styles.container}>
<Text>This is the LoadingScreen.</Text>
</View>
);
}
}

export default LoadingScreen;

在尝试测试屏幕时,我遇到了一个问题。屏幕需要一个 NavigiationScreenProps 类型的 Prop ,因为我正在访问 React Navigations navigation Prop 。这是测试文件的代码 (LoadingScreen.test.tsx):

import { LoadingScreen } from "./LoadingScreen";
import { shallow, ShallowWrapper } from "enzyme";
import React from "react";
import { View } from "react-native";
import * as navigation from "react-navigation";

const createTestProps = (props: Object) => ({
...props
});

describe("LoadingScreen", () => {
describe("rendering", () => {
let wrapper: ShallowWrapper;
let props: Object;
beforeEach(() => {
props = createTestProps({});
wrapper = shallow(<LoadingScreen {...props} />);
});

it("should render a <View />", () => {
expect(wrapper.find(View)).toHaveLength(1);
});
});
});

问题是,LoadingScreen 需要一个 navigation Prop 。

我得到错误:

[ts]
Type '{ constructor: Function; toString(): string; toLocaleString(): string; valueOf(): Object; hasOwnProperty(v: string | number | symbol): boolean; isPrototypeOf(v: Object): boolean; propertyIsEnumerable(v: string | ... 1 more ... | symbol): boolean; }' is not assignable to type 'Readonly<NavigationScreenProps<NavigationParams, any>>'.
Property 'navigation' is missing in type '{ constructor: Function; toString(): string; toLocaleString(): string; valueOf(): Object; hasOwnProperty(v: string | number | symbol): boolean; isPrototypeOf(v: Object): boolean; propertyIsEnumerable(v: string | ... 1 more ... | symbol): boolean; }'.
(alias) class LoadingScreen

我该如何解决这个问题?

我想我必须以某种方式模拟 navigation Prop 。我尝试这样做(如您所见,我在测试中从 React Navigation 导入了 *),但无法弄清楚。只有 NavigationActions 是远程有用的,但它只包含 navigate()。 TypeScript 期望一切,甚至状态,都被模拟。我如何模拟 navigation Prop ?

编辑 1: 使用 NavigationScreenProps 的方法是否正确,或者我应该使用 interface Props 方法?如果是,那么您将如何模拟比(它会导致相同的错误)。

编辑 2:使用接口(interface)和

的第二种方法
export class LoadingScreen extends Component<Props, object>

我能够“解决”这个问题。我真的不得不像这样模拟导航对象的每个属性:

const createTestProps = (props: Object) => ({
navigation: {
state: { params: {} },
dispatch: jest.fn(),
goBack: jest.fn(),
dismiss: jest.fn(),
navigate: jest.fn(),
openDrawer: jest.fn(),
closeDrawer: jest.fn(),
toggleDrawer: jest.fn(),
getParam: jest.fn(),
setParams: jest.fn(),
addListener: jest.fn(),
push: jest.fn(),
replace: jest.fn(),
pop: jest.fn(),
popToTop: jest.fn(),
isFocused: jest.fn()
},
...props
});

问题仍然存在:这是正确的吗?或者有更好的解决方案吗?

编辑 3:当我使用 JS 时,只模拟我需要的属性就足够了(通常只是导航)。但自从我开始使用 TypeScript 以来,我不得不模拟导航的每个方面。否则 TypeScript 会提示组件需要一个不同类型的 prop。

最佳答案

问题

模拟与预期类型不匹配,因此 TypeScript 报告错误。

解决方案

您可以使用类型any "to opt-out of type-checking and let the values pass through compile-time checks" .

详情

正如您提到的,在 JavaScript 中,它只模拟测试所需的内容。

在 TypeScript 中,相同的 mock 会导致错误,因为它与预期的类型不完全匹配。

在这种情况下,您知道模拟与预期类型不匹配,您可以使用 any 允许模拟通过编译时检查。


这是一个更新的测试:

import { LoadingScreen } from "./LoadingScreen";
import { shallow, ShallowWrapper } from "enzyme";
import React from "react";
import { View } from "react-native";

const createTestProps = (props: Object) => ({
navigation: {
navigate: jest.fn()
},
...props
});

describe("LoadingScreen", () => {
describe("rendering", () => {
let wrapper: ShallowWrapper;
let props: any; // use type "any" to opt-out of type-checking
beforeEach(() => {
props = createTestProps({});
wrapper = shallow(<LoadingScreen {...props} />); // no compile-time error
});

it("should render a <View />", () => {
expect(wrapper.find(View)).toHaveLength(1); // SUCCESS
expect(props.navigation.navigate).toHaveBeenCalledWith('LoginScreen'); // SUCCESS
});
});
});

关于typescript - 如何在 React Native 中使用 TypeScript 模拟 React Navigation 的导航 Prop 以进行单元测试?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52569447/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com