简体   繁体   中英

Testing React Native Functional Component With Dependency on Promise

I've got a functional component in React Native.

import { ReactElement, useEffect, useState } from "react-test-renderer/node_modules/@types/react";
import SpecialObject from "./SpecialObject";
import { getPromisedObject } from "./AccessFunctions";

export function PromiseDependencyComponent(): ReactElement {
  const [val, setVal] = useState<SpecialObject>(new SpecialObject());

  const promisedVal: Promise<SpecialObject> = getPromisedObject();

  useEffect(() => {
    setInterval(() => {
      promisedVal.then( (obj) =>
        setVal(obj); 
      );
    }, 250);
  }, []);

  return (<Text>{val.getSomeField()}</Text>);
}

I'd like to be able to test that the promised SpecialObject is retrieved correctly when the component is rendered. This is what I've got now:

import * as React from "react";
import renderer from "react-test-renderer";
import PromiseDependencyComponent from "../PromiseDependencyComponent";

it("PromiseDependencyComponent renders correctly", () => {
  const componentRenderer = renderer.create(<PromiseDependencyComponent />);
  // I've also tried using timers and componentRenderer.update() and neither worked for me.
  const tree = componentRenderer.toJSON();

  expect(tree).toMatchSnapshot();
});

This test executes and nothing breaks, I'm just not seeing the same thing as I'm seeing when running the app. When I run the app, I see the promised value being displayed after a 250ms delay. But my problem is that I want to see the updated/promised value in my test snapshot.

So what I'm seeing in my app is something like this:

  <!-- This the updated/promised SpecialObject. -->
  <Text>5</Text>

But I'm getting something like this in my test snapshot:

  <!-- This just comes from a new instance of SpecialObject, which is the initialized component state. -->
  <Text>0</Text>

What's the simplest/cleanest way to invoke some sort of update on my component so that I can verify that the promise is fulfilled when the component is rendered?

First of all, there is a popular testing library for handling various testing scenarios in React and it is called @testing-library/react . I highly suggest you use it for your React component tests.

As for the question you ask, there are methods in @testing-library/react like waitFor and await findBy... and you can use them for your async tests. (SeeAsync Methods )

So an example would be like this:

import {render, screen} from "@testing-library/react"
import MyAsyncComponent from "./MyAsyncComponent"

describe("My Async Component", () => {
  it("Updates after promise resolves", async () => {
    render(<MyAsyncComponent/>)

    const myAsyncResult = await screen.findByText("5");

    expect(myAsyncResult).toBeInTheDocument();

  })
})

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM