Данные тестирования, возвращаемые axios, обновляют DOM - PullRequest
0 голосов
/ 17 января 2019

Я пытаюсь TDD компонент React, который будет делать несколько вызовов API, но я пытаюсь проверить, как ответы влияют на DOM, как и ожидалось. В этом примере я делаю запрос на получение списка сообщений, обновляя состояние, которое затем обновляет DOM для отображения указанного списка.

Это работает в реальности, но мой тест не пройден, потому что он не может найти элемент li, который я ищу (он находит 0, а не 1), несмотря на то, что я смог увидеть элемент в выводе ошибки.

Куда я иду не так? Не стесняйтесь разрывать мои настройки теста в клочья, я только начинаю разбираться с компонентами TDDing React.

// PostList.js

import React from "react";
import axios from "axios";

class PostList extends React.Component {
  constructor(props) {
    super(props);

    this.state = {
      posts: []
    };

    this.getPosts = this.getPosts.bind(this);
  }

  async getPosts() {
    return axios.get("/api/posts/").then(response => {
      return response.data.posts;
    });
  }

  componentDidMount() {
    this.getPosts().then(posts => {
      this.setState({
        posts: posts
      });
    });
  }

  render() {
    const posts = this.state.posts.map(post => (
      <li key={post.id}>
        <strong>{post.title}</strong> {post.description}
      </li>
    ));

    return (
      <div>
        <h1>Posts:</h1>
        <ul>{posts}</ul>
      </div>
    );
  }
}

export default PostList;
// PostList.test.js

import React from "react";
import { shallow } from "enzyme";
import axios from "axios";
import MockAdapter from "axios-mock-adapter";

import PostList from "./PostList";

describe("<PostList />", () => {
  let shallowPostList;
  let posts = [{ id: 1, title: "Hello", description: "World" }];

  const getPostsMock = new MockAdapter(axios);

  const PostList = () => {
    if (!shallowPostList) {
      shallowPostList = shallow(<PostList />);
    }

    return shallowPostList;
  };

  getPostsMock
    .onGet("/api/posts/")
    .reply(200, { posts });

  beforeEach(() => {
    shallowPostList = undefined;
  });

  describe("render()", () => {
    it("renders one post item when one post exists", done => {
      const PostListItems = PostList().find("li");

      setTimeout(() => {
        expect(PostListItems).toHaveLength(1);
        done();
      }, 1);
    });
  });
});

1 Ответ

0 голосов
/ 17 января 2019

Я думаю, является ли это TDD или нет, не существенная деталь. Я также немного озадачен вашим подходом.

Решение зависит также от вашей среды тестирования. Самым популярным для React является Jest, поэтому я могу найти решение, которое работает с этим довольно хорошо.

Если бы я был на вашем месте, я бы выделил асинхронную функцию в отдельный файл, что облегчит насмешку.

import axios from 'axios';

const getPosts = async () => axios.get('/api/posts/');

export default getPosts;

Предположим, у вас есть PostList компонент в обычной папке src вместе с файлом index.js .

.
├── src
│   ├── index.js
│   ├── PostList
│       ├── __mocks__
│          ├── GetPosts.js
│       ├── PostList.js
│       ├── PostList.test.js
│       ├── GetPosts.js

Папка __ mocks __ распознается Jest и работает, как ожидается, при условии соблюдения соглашения об именовании файлов:

  • имя файла должно совпадать с тем, которое высмеивается.

Также обратите внимание на использование jest.mock('...') в тестовом файле.

Исходя из вашего ложного примера, вы можете определить нечто похожее на это в __ mocks __ / GetPosts.js .

const returnedData = [{
   id: 1,
   title: "Hello",
   description: "World"
}];

const getPosts = jest.fn().mockReturnValueOnce(() => returnedData);

export default getPosts;
// PostList.js 
...
async componentDidMount() {
   const posts = await GetPosts();
   this.setState({
      posts,
   });
}
...

И ваш тестовый файл должен выглядеть примерно так:

import React from 'react';
import { shallow } from 'enzyme';
import PostList from './PostList.js';

jest.mock('./GetPosts.js'); // Here you "tell" to Jest to mock the function.

describe('<PostList />', () => {
   let wrapper;

   beforeAll(async () => {
      wrapper = await shallow(<PostList />);
   });

   describe('componentDidMount', () => {
      it('renders an li tag', () => {
         expect(wrapper.find('li')).toHaveLength(1);
      });
   });
});
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...