有没有一种方法可以测试无需模拟就能进行API调用的代码?

时间:2020-10-19 22:51:44

标签: react-native automated-tests

我有一个FlatList,可以实现无穷的滚动。首先,它从第三方API(Marvel)获取数据。然后,当用户滚动到最后时,它会获取更多内容。我在Flatlist中存在重复ID的问题,因此想添加测试以检查此问题。但是,Jest会强制您模拟API调用。有没有一种方法可以进行模拟测试?

如果可能的话,我试图避免使用E2E测试框架,或者这是唯一的方法吗?

编辑:下面的相关代码:

import React, {useEffect, useRef} from 'react';
import {CText} from '@components/CText';
import {fetchComics} from '@apis/marvelApi';
import {useState} from 'react';
import {Comic, ComicsResponse} from '@src/types/marvel';
import {CActivityIndicator} from '@components/CActivityIndicator';
import {FlatList} from 'react-native-gesture-handler';
import {View} from 'react-native';
import {ActivityIndicatorType} from '@src/types';
import styles from './styles';

const renderItem = ({item, index}: {item: Comic; index: number}) => {
  return <CText type="paragraph">{item.title}</CText>;
};

const keyExtractor = (item: Comic) => {
  return item.id.toString();
};

/**
 * https://developer.marvel.com/docs#!/public/getComicsCharacterCollection_get_2
 * Will get 409 error if Limit greater than 100
 */
const ITEMS_PER_PAGE = 100;

interface Props {
  characterId: number;
}

const initialState = {
  offset: 0,
  totalResults: -1,
};

/**
 * For some reason this component doesn't unmount if you leave the screen
 * by pressing the back button
 */
const ComicsComponent = (props: Props) => {
  const [comics, setComics] = useState<Comic[]>(undefined);
  const [isBusy, setIsBusy] = useState(true);
  const [activityIndicatortype, setActivityIndicatorType] = useState<
    ActivityIndicatorType
  >('absolute');

  const state = useRef(initialState);
  const characterId = props.characterId;

  /**
   * This effect gets called on load and should always have offset 0
   */
  useEffect(() => {
    state.current = initialState;
    setActivityIndicatorType('absolute');
    setIsBusy(true);
    setComics(undefined);
    const offset = 0;

    fetchComics(characterId, offset, ITEMS_PER_PAGE).then(
      (response: ComicsResponse) => {
        setIsBusy(false);
        setComics(response.data.results);
        setActivityIndicatorType('small');
        state.current.totalResults = response.data.total;
      },
    );

    return () => {
      console.log('Component unmounted');
    };
  }, [props.characterId]);

  /**
   * This function gets called when the user scrolls to end of FlatList
   */
  const endReachedHandler = () => {
    if (
      state.current.totalResults > 0 &&
      state.current.offset < state.current.totalResults
    ) {
      if (isBusy) {
        return;
      }
      const newOffset = state.current.offset + ITEMS_PER_PAGE;
      state.current.offset = newOffset;
      setIsBusy(true);
      fetchComics(characterId, newOffset, ITEMS_PER_PAGE).then(
        (response: ComicsResponse) => {
        
          setIsBusy(false);
          if (newOffset > response.data.total) {
            return;
          }
          //do nothing since we reached the end
          else {
            console.log(`Offset: ${newOffset} Comics length:${comics.length}`);

            const newComics = [...comics, ...response.data.results];
            setComics(newComics);
          }
        },
      );
    }
  };

  const content = () => {
    if (comics) {
      return (
        <FlatList
          data={comics}
          renderItem={renderItem}
          keyExtractor={keyExtractor}
          onEndReachedThreshold={2}
          onEndReached={endReachedHandler}
        />
      );
    } else {
      return null;
    }
  };

  return (
    <View style={styles.flex}>
      {content()}

      {isBusy && <CActivityIndicator type={activityIndicatortype} />}
    </View>
  );
};

export {ComicsComponent};

1 个答案:

答案 0 :(得分:0)

事实证明,您可以使用axios包在React-native中的Jest测试中进行API调用。

import 'react-native';

import axios from 'axios';

const TIMEOUT = 5000;

beforeEach(() => {});

it(
  'can call Axios',
  async () => {
    const result = await axios.get('https://api.scryfall.com/sets');
    expect(result.status).toEqual(200);
    expect(result.data.object).toEqual('list');
  },
  TIMEOUT,
);

我在使用简单的获取程序包时遇到了麻烦。