本文介绍了给我的第一个组件写一个笑话测试的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我刚写完第一个 Reactjs 组件,并准备编写一些测试(我使用了 material-ui Table Toggle )。
我读到关于笑话的书,但是我仍然想念一些东西。

I just finished writing my first Reactjs component and I am ready to write some tests (I used material-ui's Table and Toggle).I read about jest and enzyme but I feel that I am still missing something.

我的组件看起来像这样(简化):

My component looks like this (simplified):

export default class MyComponent extends Component {
    constructor() {
        super()
        this.state = {
            data: []
        }

        // bind methods to this
    }

    componentDidMount() {
        this.initializeData()
    }

    initializeData() {
        // fetch data from server and setStates
    }

    foo() {
        // manuipulatig data
    }

    render() {
        reutrn (
            <Toggle
                id="my-toggle"
                ...
                onToggle={this.foo}
            >
            </Toggle>

            <MyTable
                id="my-table"
                data={this.state.data}
                ...
            >
            </MyTable>
        )
    }
}

现在可以进行测试了。我想针对以下情况编写测试:

Now for the test. I want to write a test for the following scenario:


  1. 使用模拟数据提供initializeData。

  2. 切换my-toggle

  3. 声明数据已更改(我应该声明数据本身还是更好的做法是声明my-table?)

所以我从一开始就是这样:

So I started in the very beginning with:

describe('myTestCase', () => {
    it('myFirstTest', () => {
        const wrapper = shallow(<MyComponent/>);
    }
})

我运行了它,但是失败了: ReferenceError:提取未定义

I ran it, but it failed: ReferenceError: fetch is not defined

然后我的第一个问题是,如何模拟 initializeData 来克服是否需要调用使用fetch的真实代码?

My first question is then, how do I mock initializeData to overcome the need of calling the real code that using fetch?

我遵循以下答案:并提出了以下建议:

I followed this answer: https://stackoverflow.com/a/48082419/2022010 and came up with the following:

describe('myTestCase', () => {
    it('myFirstTest', () => {
        const spy = jest.spyOn(MyComponent.prototype, 'initializeData'
        const wrapper = mount(<MyComponent/>);
    }
})

但我仍然遇到相同的错误(我也使用 componentDidMount 而不是 initializeData 进行了尝试,但最终还是一样)。

But I am still getting the same error (I also tried it with componentDidMount instead of initializeData but it ended up the same).

更新:我错了,我确实得到了未定义的提取错误,但这一次它来自Table组件(它是material-ui的Table的包装)现在,我开始考虑它的过程中确实有很多抓取 ...我想知道那时该如何处理它们。

Update: I was wrong. I do get a fetch is not defined error but this time it is coming from the Table component (which is a wrap for material-ui's Table). Now that I come to think about it I do have a lot of "fetches" along the way... I wonder how to take care of them then.

推荐答案

fetch 在浏览器中受支持,但jest / enzyme在Node中运行环境,因此 fetch 在测试代码中不是全局可用的函数。有几种方法可以解决此问题:

fetch is supported in the browser, but jest/enzyme run in a Node environment, so fetch isn't a globally available function in your test code. There are a few ways you can get around this:

1:全球范围内k 获取-这可能是最简单的解决方案,但也许不是最干净的解决方案。

1: Globally mock fetch - this is probably the simplest solution, but maybe not the cleanest.

global.fetch = jest.fn().mockResolvedValue({
  json: () => /*Fake test data*/
  // or mock a response with `.text()` etc if that's what
  // your initializeData function uses
});

2:将您的提取调用抽象到服务层中,并将其作为依赖项注入-这将使您代码更灵活(尽管样板更多),因为您可以将获取实现隐藏在您选择的任何接口后面。然后,在将来的任何时候,如果您决定使用其他提取库,都可以在服务层中交换实现。

2: Abstract your fetch call into a service layer and inject that as a dependency - This will make your code more flexible (more boilerplate though), since you can hide fetch implementation behind whatever interface you choose. Then at any point in the future, if you decide to use a different fetch library, you can swap out the implementation in your service layer.

// fetchService.js
export const fetchData = (url) => {
  // Simplified example, only takes 'url', doesn't
  // handle errors or other params.
  return fetch(url).then(res => res.json());
}

// MyComponent.js
import {fetchService} from './fetchService.js'

class MyComponent extends React.Component {
  static defaultProps = {
    // Pass in the imported fetchService by default. This
    // way you won't have to pass it in manually in production
    // but you have the option to pass it in for your tests
    fetchService
  }
  ...
  initializeData() {
    // Use the fetchService from props
    this.props.fetchService.fetchData('some/url').then(data => {
      this.setState({ data });
    })
  }
}

// MyComponent.jest.js
it('myFirstTest', () => {
  const fetchData = jest.fn().mockResolvedValue(/*Fake test data*/);
  const fetchService = { fetchData };
  const wrapper = mount(<MyComponent fetchService={fetchService} />);
  return Promise.resolve().then(() = {
    // The mock fetch will be resolved by this point, so you can make
    // expectations about your component post-initialization here
  })
}

这篇关于给我的第一个组件写一个笑话测试的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-13 07:48