【问题标题】:Service method mock with Jest in React app在 React 应用程序中使用 Jest 模拟服务方法
【发布时间】:2021-11-16 11:37:20
【问题描述】:

我将 React 与 Typescript 和 Jest 一起用于单元测试。我使用酶。

我正在尝试了解 Jest 的模拟功能,并专门确定有什么问题。

我已经使用带有 typescript 的 create-react-app 创建了一个反应应用程序,即

npx create-react-app my-app --template typescript

我的下一步是在 src 目录中创建以下内容。

// services/serviceResponse.ts

export interface ServiceResponse {
    label: string;
    id: string;
  }

// services/myservice.ts

import { ServiceResponse } from "./serviceResponse";

const cannedServiceResponse: ServiceResponse[] = [
    {
        label: 'label1',
        id: 'id1',
    },
    {
        
        label: 'label2',
        id: 'id2',
    },
]

async function GetServiceData(): Promise<ServiceResponse[] | Error> {
    return cannedServiceResponse;
}
  
export default {
    GetServiceData,
};
  
// components/mycomponent.tsx
import React, { useState, useEffect } from 'react';
import myservice from '../services/myservice';
import { Row } from 'react-bootstrap';
import { ServiceResponse } from '../services/serviceResponse';

export const MyComponent = () => {
    const [data, setData] = useState<ServiceResponse[] | undefined>();

    useEffect(() => {
        const fetchData = async () => {
        const serviceData = await myservice.GetServiceData();
        if (!(serviceData instanceof Error)) {
            setData(serviceData);
        }
        };

        fetchData();
    }, []);

    if (!data) {
        return <></>;
    }

    return (
        <>
            <Row xs={1} md={4} className="col-lg-12">
            </Row>
        </>
    );
};

然后我想通过模拟从服务方法GetServiceData 返回的数据来对组件进行单元测试。我的测试组件代码是

// components/mycomponents.test.tsx
import React from 'react';
import TestRenderer from 'react-test-renderer';
import { MyComponent } from './mycomponent';
import myservice from '../services/myservice';
import { Row } from 'react-bootstrap';
import { ServiceResponse } from '../services/serviceResponse';

const mockData: ServiceResponse[] = [
  { label: 'a', id: 'b'},
  { label: 'f', id: 'g'},
];

describe('mycomponent', () => {
  
  it('MyComponent returns data', () => {
    jest.spyOn(myservice, 'GetServiceData').mockImplementation(
      () =>
        new Promise<ServiceResponse[]>((resolve) => {
          resolve(mockData);
        })
    );

    const component = TestRenderer.create(<MyComponent />);
    const componentInstance = component.root;
    console.log(component.toJSON());
    // TODO - Add an expect line here for assertion
  });
});

问题在于 jest.spyOn() 没有模拟数据。我也尝试使用以下内容

jest.mock('../services/myservice', () => ({
  GetServiceData: jest.fn().mockReturnValue(() => Promise.resolve(mockData)),
}));

我知道有一些方法可以像使用 here 一样使用 Enzyme 进行测试,但我试图了解用 Jest 进行模拟以及我做错了什么。

【问题讨论】:

    标签: reactjs typescript unit-testing jestjs


    【解决方案1】:

    jest.spyOn() 应该可以工作。您需要使用 act 的异步版本来应用已解决的承诺。可以参考官方例子testing-recipes.html#data-fetching

    import React from 'react';
    import { act, create } from 'react-test-renderer';
    import { MyComponent } from './mycomponent';
    import myservice from '../services/myservice';
    import { ServiceResponse } from '../services/serviceResponse';
    
    const mockData: ServiceResponse[] = [
      { label: 'a', id: 'b' },
      { label: 'f', id: 'g' },
    ];
    
    describe('mycomponent', () => {
      it('MyComponent returns data', async () => {
        jest.spyOn(myservice, 'GetServiceData').mockResolvedValue(mockData);
        let root;
        await act(async () => {
          root = create(<MyComponent />);
        });
        console.log(root.toJSON());
      });
    });
    

    测试结果:

     PASS  examples/69293771/components/mycomponent.test.tsx (7.271 s)
      mycomponent
        ✓ MyComponent returns data (25 ms)
    
      console.log
        { type: 'div', props: {}, children: [ 'row' ] }
    
          at examples/69293771/components/mycomponent.test.tsx:19:13
    
    Test Suites: 1 passed, 1 total
    Tests:       1 passed, 1 total
    Snapshots:   0 total
    Time:        7.755 s, estimated 9 s
    

    【讨论】:

    • 这很棒,正是我所追求的。
    猜你喜欢
    • 2018-04-28
    • 2022-06-28
    • 2023-01-30
    • 2021-09-13
    • 2021-09-14
    • 2019-12-09
    • 2019-01-08
    • 2020-08-22
    • 2020-06-01
    相关资源
    最近更新 更多