Testing with jest and React Native Testing Library

huangapple go评论59阅读模式
英文:

Testing with jest and React Native Testing Library

问题

我是你的中文翻译,以下是你提供的内容的翻译:


我是一个测试新手

我正在尝试使用Expo、Jest和React Native Testing Library测试React Native应用程序

我编写了一个简单的屏幕,从一个API获取数据并在屏幕上用标签显示第一个元素


import { StyleSheet, Text, View } from "react-native"; 
import React, { useEffect, useState } from "react"; 
import axios from "axios"; 

const ReadPostsFromTypicode = () => { 
  const [list, setList] = useState([]); 

  const readFromTypicode = async () => { 
    const response = await axios.get( 
      "https://jsonplaceholder.typicode.com/posts" 
    ); 
    setList(response.data); 
  }; 

  useEffect(() => { 
    readFromTypicode(); 
  }, []); 

  return ( 
    <View style={{ margin: 25 }}> 
      <Text>{list[0]?.title}</Text> 
    </View> 
  ); 
}; 

export default ReadPostsFromTypicode; 

const styles = StyleSheet.create({}); 

我还在使用MSW,所以第一个元素将是“Hello”:


import { rest } from "msw"; 
export const handlers = [ 
  rest.get("https://jsonplaceholder.typicode.com/posts", (req, res, ctx) => { 
    return res( 
      ctx.json([{ userId: 1, id: 1, title: "Hello", body: "Hello World!" }]) 
    ); 
  }), 
]; 

但是当我运行测试时:

import React from "react"; 
import { render, screen, s } from "@testing-library/react-native"; 
import ReadPostsFromTypicode from "../src/screens/ReadPostsFromTypicode"; 

describe("ReadPostsFromTypicode", () => { 
  it("has 1 text", async () => { 
    render(<ReadPostsFromTypicode />); 
    expect(screen.getByText("Hello")).toBeTruthy(); 
  }); 
}); 

我在测试中收到了一个错误,说“无法找到带有文本:Hello”的元素。这是测试输出:

Testing with jest and React Native Testing Library

尽管我检查过模拟服务器工作正常,状态也被正确设置。

但我也收到了一个奇怪的警告:

   警告:在测试中未在act(...)中包装ReadPostsFromTypicode的更新。

    在测试时,导致React状态更新的代码应该包装在act(...)中:

    act(() => { 
      /* 触发更新状态的事件 */ 
    }); 

    /* 对输出进行断言 */ 

    这确保您正在测试用户在浏览器中看到的行为。在 https://reactjs.org/link/wrap-tests-with-act 了解更多信息

        在 ReadPostsFromTypicode (C:\Rafael\react-tests\create-expo-app-msw\src\screens\ReadPostsFromTypicode.js:6:35) 
      11 |     ); 
      12 |     console.log(response.data); 
    > 13 |     setList(response.data); 
         |     ^ 
      14 |   }; 
      15 | 
      16 |   useEffect(() => { 

似乎它不喜欢使用状态变量。

我将渲染包装在act中,如下所示:

import React from "react"; 
import { render, screen, act } from "@testing-library/react-native"; 

import ReadPostsFromTypicode from "../src/screens/ReadPostsFromTypicode"; 

describe("ReadPostsFromTypicode", () => { 
  it("has 1 text", async () => { 
    act(() => render(<ReadPostsFromTypicode />)); 
    expect(screen.getByText("Hello")).toBeTruthy(); 
  }); 
}); 

我读到渲染已经包装在Act中,但我不知道要包装什么,现在我得到了这个错误:

    尝试检测主机组件名称触发了以下错误:

    无法访问未安装的测试渲染器的.root

    似乎存在一个配置问题,阻止React Native Testing Library正常工作。
    请检查您是否使用兼容的React Native和React Native Testing Library版本。

       6 | describe("ReadPostsFromTypicode", () => {
       7 |   it("has 1 text", async () => {
    >  8 |     act(() => render(<ReadPostsFromTypicode />));
         |                     ^
       9 |     // render(<ReadPostsFromTypicode />);
      10 |     expect(screen.getByText("Hello")).toBeTruthy();
      11 |   });

我需要知道我做错了什么

提前感谢您的帮助


希望对你有所帮助。如果你有任何其他问题,请随时问。

英文:

I’m a newbie with testing

I’m trying to get a grip on testing React Native with Expo, Jest and React Native Testing Library

I wrote a simple screen that takes data from an API and writes the first element in the screen with a < Text >


import { StyleSheet, Text, View } from &quot;react-native&quot;; 
import React, { useEffect, useState } from &quot;react&quot;; 
import axios from &quot;axios&quot;; 

const ReadPostsFromTypicode = () =&gt; { 
  const [list, setList] = useState([]); 

  const readFromTypicode = async () =&gt; { 
    const response = await axios.get( 
      &quot;https://jsonplaceholder.typicode.com/posts&quot; 
    ); 
    setList(response.data); 
  }; 

  useEffect(() =&gt; { 
    readFromTypicode(); 
  }, []); 

  return ( 
    &lt;View style={{ margin: 25 }}&gt; 
      &lt;Text&gt;{list[0]?.title}&lt;/Text&gt; 
    &lt;/View&gt; 
  ); 
}; 

export default ReadPostsFromTypicode; 

const styles = StyleSheet.create({}); 

I’m also using MSW, so the first element would be “Hello”:


import { rest } from &quot;msw&quot;; 
export const handlers = [ 
  rest.get(&quot;https://jsonplaceholder.typicode.com/posts&quot;, (req, res, ctx) =&gt; { 
    return res( 
      ctx.json([{ userId: 1, id: 1, title: &quot;Hello&quot;, body: &quot;Hello World!&quot; }]) 
    ); 
  }), 
]; 

But when I run the test:

import React from &quot;react&quot;; 
import { render, screen, s } from &quot;@testing-library/react-native&quot;; 
import ReadPostsFromTypicode from &quot;../src/screens/ReadPostsFromTypicode&quot;; 

describe(&quot;ReadPostsFromTypicode&quot;, () =&gt; { 
  it(&quot;has 1 text&quot;, async () =&gt; { 
    render(&lt;ReadPostsFromTypicode /&gt;); 
    expect(screen.getByText(&quot;Hello&quot;)).toBeTruthy(); 
  }); 
}); 

I get an error in the test, saying that “Unable to find an element with text: Hello”
This is the test output:

Testing with jest and React Native Testing Library

Even though I checked that the mocked server worked ok, and the state was being set right.

But I also get a strange warning:

   Warning: An update to ReadPostsFromTypicode inside a test was not wrapped in act(...). 

    When testing, code that causes React state updates should be wrapped into act(...): 

    act(() =&gt; { 
      /* fire events that update state */ 
    }); 

    /* assert on the output */ 

    This ensures that you&#39;re testing the behavior the user would see in the browser. Learn more at https://reactjs.org/link/wrap-tests-with-act 

        at ReadPostsFromTypicode (C:\Rafael\react-tests\create-expo-app-msw\src\screens\ReadPostsFromTypicode.js:6:35) 
      11 |     ); 
      12 |     console.log(response.data); 
    &gt; 13 |     setList(response.data); 
         |     ^ 
      14 |   }; 
      15 | 
      16 |   useEffect(() =&gt; { 

It seems that it doesn’t like the use of the state variable

I wrapped the render with act like so:

import React from &quot;react&quot;;
import { render, screen, act } from &quot;@testing-library/react-native&quot;;

import ReadPostsFromTypicode from &quot;../src/screens/ReadPostsFromTypicode&quot;;

describe(&quot;ReadPostsFromTypicode&quot;, () =&gt; {
  it(&quot;has 1 text&quot;, async () =&gt; {
    act(() =&gt; render(&lt;ReadPostsFromTypicode /&gt;));
    expect(screen.getByText(&quot;Hello&quot;)).toBeTruthy();
  });
});

I read that the render is already wrapped with Act, but I don't know what to wrap, now I get this error:

    Trying to detect host component names triggered the following error:

    Can&#39;t access .root on unmounted test renderer

    There seems to be an issue with your configuration that prevents React Native Testing Library from working correctly.
    Please check if you are using compatible versions of React Native and React Native Testing Library.

       6 | describe(&quot;ReadPostsFromTypicode&quot;, () =&gt; {
       7 |   it(&quot;has 1 text&quot;, async () =&gt; {
    &gt;  8 |     act(() =&gt; render(&lt;ReadPostsFromTypicode /&gt;));
         |                     ^
       9 |     // render(&lt;ReadPostsFromTypicode /&gt;);
      10 |     expect(screen.getByText(&quot;Hello&quot;)).toBeTruthy();
      11 |   });

I need to know what I am doing wrong

Thanks in advance

答案1

得分: 1

你应该能够使用React Testing Library提供的waitFor方法来包裹你的断言。

describe("ReadPostsFromTypicode", () => { 
  it("has 1 text", async () => { 
    render(<ReadPostsFromTypicode />); 
    await waitFor(() => {
      expect(screen.getByText("Hello")).toBeTruthy(); 
    });
  }); 
}); 

这里是关于React测试异步状态更新的文章。

这里是React Testing Library关于异步测试的文档。

我不能百分之百确定这是你的解决方案,因为我目前无法进行测试,但如果你在尝试后仍然遇到问题,请告诉我,我会尝试复制你的问题。祝好!

英文:

You should be able to wrap your assertion with the waitFor method provided by React Testing Library.

describe(&quot;ReadPostsFromTypicode&quot;, () =&gt; { 
  it(&quot;has 1 text&quot;, async () =&gt; { 
    render(&lt;ReadPostsFromTypicode /&gt;); 
    await waitFor(() =&gt; {
      expect(screen.getByText(&quot;Hello&quot;)).toBeTruthy(); 
    });
  }); 
}); 

Here is an article on React Testing async state updates

Here are the React Testing Library docs on async testing

I am not 100% sure this is your solution as I am unable to test it myself at the moment, but let me know if you still have issues after trying it and I will try to replicate your issues. Cheers!

huangapple
  • 本文由 发表于 2023年2月27日 10:14:46
  • 转载请务必保留本文链接:https://go.coder-hub.com/75576274.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定