加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

如何使用React Native中的TypeScript模拟React Navigation的单元

发布时间:2020-12-15 16:20:22 所属栏目:百科 来源:网络整理
导读:我正在用TypeScript构建一个React Native应用程序.对于我的导航,我使用React Navigation,对于我的单元测试,我使用Jest和Enzyme. 这是我的一个屏幕(LoadingScreen.tsx)的(精简的)代码: import styles from "./styles";import React,{ Component } from "reac
我正在用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:
当我使用JS时,只需要模拟我需要的属性(通常只是导航)就足够了.但是自从我开始使用TypeScript以来,我不得不模仿导航的每个方面.否则TypeScript会抱怨该组件需要一个具有不同类型的道具.

解决方法

问题

模拟与预期类型不匹配,因此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
    });
  });
});

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读