如何使用React Native中的TypeScript模拟React Navigation的单元
我正在用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类型的道具,因为我正在访问React Navigations导航道具.这是测试文件的代码(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需要导航道具. 我收到错误: [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 我怎样才能解决这个问题? 我想我不得不嘲笑导航道具.我试过这样做(你可以看到我在我的测试中从React Navigation导入*),但是无法弄明白.只有NavigationActions是远程有用的,但它只包含navigate(). TypeScript期望模拟所有内容,甚至是状态.我怎么能嘲笑导航道具呢? 编辑1:使用NavigationScreenProps的方法是否正确或我应该使用接口Props方法?如果是,你会如何模拟(它导致相同的错误). 编辑2: 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: 解决方法
问题
模拟与预期类型不匹配,因此TypeScript报告错误. 解 您可以使用任何类型“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",() => { 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 }); }); }); (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |