简体   繁体   English

React 测试库,组件单元测试

[英]React Testing Library, Component Unit Tests

I am trying to build a test unit for my simple React Application using React Testing Library.我正在尝试使用 React 测试库为我的简单 React 应用程序构建一个测试单元。 I readed all docs and get stuck in it.我阅读了所有文档并陷入其中。

API was created by create React app. API 是通过创建 React 应用程序创建的。 One of the feature is that user can change theme.其中一项功能是用户可以更改主题。 There is setTheme hook that going to change theme "dark" and "light".有 setTheme 钩子可以改变主题“黑暗”和“光明”。

App.js应用程序.js

const App = () => { 
const [theme, setTheme] = useState('dark'); 
return ( <div>
           <Header theme={theme} setTheme={setTheme} />
        </div>)
};

Header.js Header.js

import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'

const Header = props => {
  return (
    <header data-testid="header">
      <h1><span className="highlight">Github Users</span></h1>
      {props.theme === "dark" ? 
        <FontAwesomeIcon data-testid="button" icon="sun" size="2x" color="#dcba31"  onClick={ () => props.setTheme('light') }/>
        :  <FontAwesomeIcon icon="moon" size="2x" color="#1c132d" onClick={ () => props.setTheme('dark') }/>}
    </header>
  );
}
export default Header;

In Header component I added arrow function that changes color of theme.在 Header 组件中,我添加了改变主题颜色的箭头 function。

Now I am trying to write a test that's gonna test Header Component.现在我正在尝试编写一个测试 Header 组件的测试。 Expected result is that after first render Header component shall render icon "sun".预期的结果是在第一次渲染 Header 组件后应该渲染图标“太阳”。 After user click on it header shall return icon "moon".用户点击后 header 将返回图标“月亮”。

There is something that i try but it's not working as I mention.我尝试了一些东西,但正如我提到的那样它不起作用。

Header.test.js Header.test.js

import React from 'react';
import { render, cleanup } from "@testing-library/react"
import '@testing-library/jest-dom/extend-expect';
import { act } from "react-dom/test-utils";


import Header from '../components/Header';

afterEach(cleanup);

describe("Header Component", () => { 
    it("first render should return a sun icon", () => {
        const {getByTestId } = render(<Header />)
        expect(getByTestId("header"). // What method uses here? To check if it is icon sun or moon ? )

    })
    it("after mouse click event should return a moon icon", () => {
        const button = document.querySelector("svg"); // it is correct way to add a svg element as a button ?
        act( () => {
            button.dispatchEvent(new MouseEvent('click', {bubbles: true}));
        })
        expect(getByTestId("header").  // again what to write here to test it after click ?
    })
})

I am sure that there is some other way to check first render and then after click what's Header component rendering.我确信还有其他方法可以检查第一次渲染,然后单击 Header 组件渲染。 I think that problem is that there is another Component that is rendered conditionaly.我认为这个问题是有另一个组件是有条件地呈现的。 If it is text there is no problem, but after render there is svg element with some attributes like icon="sun" / icon="moon".如果是文本没有问题,但渲染后有 svg 元素具有一些属性,如 icon="sun" / icon="moon"。

Live version of project项目的现场版本

Github Repo Link Github回购链接

Questions:问题:

  1. How to properly test that Header component?如何正确测试 Header 组件?
  2. How to pass props in test for example I want to use that setTheme hook in test how to do it?如何在测试中传递道具例如我想在测试中使用那个 setTheme 钩子怎么做?

There's many ways to do this and I can recommend the articles here https://kentcdodds.com/blog/?q=test to get you started.有很多方法可以做到这一点,我可以在这里推荐文章https://kentcdodds.com/blog/?q=test让你开始。 As for your current set-up I'd change some stuff that I find helpful writing unit tests:至于您当前的设置,我会更改一些我认为编写单元测试有用的东西:

  • Use data-testid to find elements, eg "first render should return a sun icon" can be confirmed by expect(getByTestId('svg-sun')).toBeDefined() , which is a pattern I like使用data-testid查找元素,例如“第一次渲染应该返回一个太阳图标”可以通过expect(getByTestId('svg-sun')).toBeDefined()来确认,这是我喜欢的模式
  • Structure your it 's like stubbing-rendering-assertions and only test one thing in each test, for instance, in your second it you're lacking a rendering part of the test构造你的it就像 stubbing-rendering-assertions 并且在每个测试中只测试一件事,例如,在你的第二个it你缺少测试的渲染部分

Regarding your question regarding passing the props, you can pass it as render(<Header theme={theme} setTheme={setThemeStub}/>) where const setThemeStub = jest.fn() .关于您关于传递道具的问题,您可以将其传递为render(<Header theme={theme} setTheme={setThemeStub}/>) where const setThemeStub = jest.fn() This allows you to make assertions as expect(setThemeStub).toBeCalledWith(...)这允许您按照expect(setThemeStub).toBeCalledWith(...)进行断言

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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