最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Write test to check local setState call with jest and react-testing-library - Stack Overflow

programmeradmin4浏览0评论

I am currently using react-testing-library and can't seem to work out how to test setState for ponents.

In the following example, I am trying to test that the number of items loaded is correct based on the data from the API. Will later on expand this to test things like the interactions between of the items.

Component:

...

ponentDidMount() {
    this.getModules();
}

getModules () {
    fetch('http://localhost:4000/api/query')
    .then(res => res.json())
    .then(res => this.setState({data : res.data}))
    .catch(err => console.error(err))
}

...

render() {
  return(
      <div data-testid="list">
          this.state.data.map((item) => {
              return <Item key={item.id} data={item}/>
          })
      </div>
  )
}

Test:

...

function renderWithRouter(
    ui,
    {route = '/', history = createMemoryHistory({initialEntries: [route]})} = {},) {
    return {
        ...render(<Router history={history}>{ui}</Router>),
        history,
    }
}

...

test('<ListModule> check list items', () => {
     const data = [ ... ]
     //not sure what to do here, or after this
     const { getByTestId } = renderWithRouter(<ListModule />)

     ...

     //test the items loaded
     expect(getByTestId('list').children.length).toBe(data.length)

     //then will continue testing functionality

})

I understand this has to do with jest mock functions, but don't understand how to make them work with setting states, or with simulating an API.

Sample Implementation (working!)

With more practice and learning about making ponents testable, I was able to get this working. Here is a full example for reference:

const data = [...]

fetchMock.restore().getOnce('http://localhost:4000/api/query', JSON.stringify(data));

const { getByText } = renderWithRouter(<ListModule />)

const listItem = await waitForElement(() => getByText('Sample Test Data Title'))

I am currently using react-testing-library and can't seem to work out how to test setState for ponents.

In the following example, I am trying to test that the number of items loaded is correct based on the data from the API. Will later on expand this to test things like the interactions between of the items.

Component:

...

ponentDidMount() {
    this.getModules();
}

getModules () {
    fetch('http://localhost:4000/api/query')
    .then(res => res.json())
    .then(res => this.setState({data : res.data}))
    .catch(err => console.error(err))
}

...

render() {
  return(
      <div data-testid="list">
          this.state.data.map((item) => {
              return <Item key={item.id} data={item}/>
          })
      </div>
  )
}

Test:

...

function renderWithRouter(
    ui,
    {route = '/', history = createMemoryHistory({initialEntries: [route]})} = {},) {
    return {
        ...render(<Router history={history}>{ui}</Router>),
        history,
    }
}

...

test('<ListModule> check list items', () => {
     const data = [ ... ]
     //not sure what to do here, or after this
     const { getByTestId } = renderWithRouter(<ListModule />)

     ...

     //test the items loaded
     expect(getByTestId('list').children.length).toBe(data.length)

     //then will continue testing functionality

})

I understand this has to do with jest mock functions, but don't understand how to make them work with setting states, or with simulating an API.

Sample Implementation (working!)

With more practice and learning about making ponents testable, I was able to get this working. Here is a full example for reference: https://gist.github./alfonsomunozpomer/de992a9710724eb248be3842029801c8

const data = [...]

fetchMock.restore().getOnce('http://localhost:4000/api/query', JSON.stringify(data));

const { getByText } = renderWithRouter(<ListModule />)

const listItem = await waitForElement(() => getByText('Sample Test Data Title'))
Share Improve this question edited Feb 9, 2020 at 16:28 Charklewis asked Nov 13, 2018 at 21:54 CharklewisCharklewis 5,7016 gold badges40 silver badges82 bronze badges 1
  • This is exactly same problem, stackoverflow./questions/52767157/… . getModules doesn't return a promise that could be chained in tests. fetch should be mocked, as the answer suggests. – Estus Flask Commented Nov 14, 2018 at 7:17
Add a ment  | 

1 Answer 1

Reset to default 5

You should avoid testing setState directly since that is an implementation detail of the ponent. You are on the right path to testing that the correct number of items are rendered. You can mock the fetch function by either replacing window.fetch with a Jest mock function or using the fetch-mock library to handle the heavy lifting for you.

// Note that this method does not build the full response object like status codes, headers, etc.
window.fetch = jest.fn(() => {
  return Promise.resolve({
    json: () => Promise.resolve(fakeData),
  });
});

OR

import fetchMock from "fetch-mock";
fetchMock.get(url, fakeData);
发布评论

评论列表(0)

  1. 暂无评论