【问题标题】:React Context test component that contains both Context.Provider and Context.Consumer包含 Context.Provider 和 Context.Consumer 的 React Context 测试组件
【发布时间】:2020-07-19 22:02:08
【问题描述】:

我正在尝试测试一个同时包含 React Context 的提供者和消费者的组件。请参阅下面的 App.tsx。 提供者在一个也处理状态的包装类中。

如何模拟 ConfigurationContextProvider 包装类,以便它可以正确地向消费者提供 loadedStatus 值以测试 App.tsx 的各种呈现?

App.tsx:

    public render(): React.ReactNode {
    return (
      <ConfigurationContextProvider>
        <ConfigurationContext.Consumer>
          { ({ 
            loadedStatus,
          }): ReactElement => {
            switch( loadedStatus ){
              case ConfigStatus.GoodConfiguration:
                return ( this.renderApp());
              case ConfigStatus.NotLoaded:
                return ( this.renderUnloadedApp() );
              case ConfigStatus.BadConfiguration:
                return ( this.renderBadConfiguration() );
            }
          }}
        </ConfigurationContext.Consumer> 
      </ConfigurationContextProvider>
    )}

ContextProvider.tsx:

    export const ConfigurationContext = React.createContext<ConfigurationState | undefined>(undefined);

    export enum ConfigStatus {
      NotLoaded,
      BadConfiguration,
      GoodConfiguration
    }

    export interface ConfigurationState{
      loadedStatus: ConfigStatus;
      baseUrl: URL;
    }

    export class ConfigurationContextProvider extends Component< {}, ConfigurationState> {

      constructor( props: {} ){
        super(props);
        this.state = { 
          loadedStatus: ConfigStatus.NotLoaded,
          baseUrl: null
        }
      }

      async componentDidMount(): Promise<void> {
        await this.loadConfiguration();
      }

      setConfiguration(configuration: Response): void {
        const URL_KEY = 'BASE_URL';
        const URL_VALUE = configuration[URL_KEY];
        if (!Object.prototype.hasOwnProperty.call(configuration, URL_KEY))
        {
          this.setState({ loadedStatus: ConfigStatus.BadConfiguration });
          console.error(`Missing field in configs: ${ URL_KEY }`);
        }
        else {
          try{
            this.setState({
              loadedStatus: ConfigStatus.GoodConfiguration, 
              baseUrl: new URL(URL_VALUE),
            });
          }
          catch {
            this.setState({ loadedStatus: ConfigStatus.BadConfiguration });
            console.error(`Bad URL in environment configs - ${ URL_KEY } : ${ URL_VALUE }`);
          }
        }
      }

      loadConfiguration(): Promise<void> {
        const configPromise: Promise<Response> = fetch('./env.json');
        return configPromise.then( (response) => response.json())
          .then( (config: Response) => this.setConfiguration(config));
      }

      render(): React.ReactNode {
        return (
          <ConfigurationContext.Provider value = { { 
            ...this.state,
          } }>
            {this.props.children}
          </ConfigurationContext.Provider>
        )
      }
    }

【问题讨论】:

    标签: typescript mocking jestjs react-context react-testing-library


    【解决方案1】:

    发现最简单的方法是监视 ConfigurationContextProvider 的 loadConfig 函数,并根据需要将响应设置为 setConfig。这种方式可以测试各种结果并根据需要进行完整的上下文/状态更新。

    jest.spyOn(
      ConfigurationContextProvider.prototype, 'loadConfiguration').mockImplementation(
        function(this: ConfigurationContextProvider) {
          this.setConfiguration( { BASE_URL: 'http://localhost:8080' });
          return Promise.resolve();
        }
    );
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-11-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-11-19
      • 1970-01-01
      • 1970-01-01
      • 2018-03-12
      相关资源
      最近更新 更多