首页 > 解决方案 > 在反应组件中使用 msw 模拟 fetch 不起作用

问题描述

我目前有这个反应组件,它显示从 api 检索的服务列表(为简单起见删除了一些代码):

function Services(props) {
    
    const [services, setServices] = useState([]);
    const [page_nr, setPage_nr] = useState(0);
    const [nameSearch, setNameSearch] = useState("");
    const [domainSearch, setDomainSearch] = useState("");

    let match = useRouteMatch();

    let num_on_page = 20;
    

    const get_services = () => {
        let skip = page_nr*num_on_page;
        fetch('https://myurl/api/services?limit={num_on_page}&skip={skip}', {
          method: 'GET'
        })
          .then((res) => res.json()) 
          .then((result) => setServices(result._embedded.serviceList))
          .catch((err) => console.log('error'))
      }

    const listItems = services.map((service) =>
        <li key={service.id}><Link to={`${match.url}/${service.id}`}>
            <Service name={service.name} domain={service.domain} description={service.description} /></Link></li>
    );

    useEffect(() => {
        
        if (nameSearch === "" || domainSearch === "") {
            get_services();
        }
    });

    return (
        <Switch>
        <Route path={`${match.path}/create`} component={ServiceCreate}/>
        <Route path={`${match.path}/:id`} component={ServicePage}/>
        <Route path={match.path}>
            <div className="Services">
                <h1>Diensten</h1>
                <hr id="services_line"/>
                <Link to={`${match.url}/create`}>
                    <button type="button" className="btn btn-primary">Nieuwe Dienst</button>
                </Link>
                <ul>{listItems}</ul>
                <input type="button" value="Vorige" disabled={page_nr == 0} onClick={() => setPage_nr(page_nr-1)}/>
                <input type="button" value="Volgende" disabled={services.length < num_on_page} onClick={() => setPage_nr(page_nr+1)}/>
            </div>
        </Route>
    </Switch>
    );
}

export default Services;

我编写了以下测试代码,我想模拟 fetch 函数,以便我可以测试渲染的数量是否正确,这里我使用 Mock Service Worker:

import 'whatwg-fetch';
import { setupWorker, rest } from 'msw';
import { setupServer } from 'msw/node';

const fakeData = {
  _embedded: {
    serviceList: [{id: 100, name:"naam 1", description:"een omschrijving van de dienst", domain: "domein 1"}, 
    {id: 101, name:"naam 1", description:"een omschrijving van de dienst", domain: "domein 1"}, 
    {id: 102, name:"naam 1", description:"een omschrijving van de dienst", domain: "domein 1"}, 
    {id: 104, name:"naam 1", description:"een omschrijving van de dienst", domain: "domein 1"}, 
    {id: 105, name:"naam 1", description:"een omschrijving van de dienst", domain: "domein 1"}, 
    {id: 106, name:"naam 1", description:"een omschrijving van de dienst", domain: "domein 1"}, 
    {id: 107, name:"naam 1", description:"een omschrijving van de dienst", domain: "domein 1"}, 
    {id: 108, name:"naam 1", description:"een omschrijving van de dienst", domain: "domein 1"}]
  }
};

const server = setupServer(
  rest.get("https://sel2-4.ugent.be/api/services", (req, res, ctx) => {
    return res(ctx.status(200), ctx.json(fakeData))
  }));

describe('Test Services', () => {
  beforeAll(() => server.listen());
  afterAll(() => server.close());
  
  let wrapper = null;
  const history = createMemoryHistory()
  history.push('/services')
  beforeEach(async () => {
    await act(async () => {
      wrapper = mount(<Router history={history}><Services/></Router>);  
    }); 
  wrapper.update();
  })
  afterEach(() => {
    wrapper = null;
    server.resetHandlers()
  })


  it('should render correct fetched amount', async () => {
    expect(wrapper.find(Service).length).toBe(8);
  })
});

当我运行测试它失败并显示长度为 0(如果我编辑const [services, setServices] = useState([]);为数组中已有项目,则长度不同于 0)。似乎 fetch 甚至没有被执行。现在我尝试了许多选项来模拟 fetch 函数,但它们似乎都不起作用。我在这里做错了什么以及测试使用 fetch 的反应钩子的方法应该是什么?

标签: javascriptreactjsjestjsenzymemsw

解决方案


推荐阅读