【问题标题】:How to properly mock ES6 class dependencies如何正确模拟 ES6 类依赖项
【发布时间】:2019-07-27 01:48:04
【问题描述】:

我在为我的 React 组件所依赖的服务类工作而苦苦挣扎——在组件内部初始化的类。我正在使用 Jest“手动模拟”方法。我正在打电话给jest.mock,但每次我运行测试时,他们都使用真正的服务类而不是模拟。

我已经看到它表明我正在尝试做的事情(在下面的示例中,模拟 UserService)对于 Jest 是不可能的。我知道在这个例子中,getUsers 调用可能只是一个导出函数,但在我的实际项目中,我会有需要模拟的完整类;这只是一个过于简单的例子。

我的问题归结为:我可以在使用 Jest 测试 React 组件时模拟出这样的类吗?如果可以,我缺少什么?这是一个不工作的模拟示例。

编辑:GitHub 中的代码:https://github.com/cvs-mrussell/ReactJestMockTest

编辑 2:如果我将组件转换为类,则模拟工作。测试 React 钩子有问题吗?阅读此内容,在 React 18.9.0-alpha 之前,在 useEffect 中使用异步调用进行测试似乎很棘手,此时专门引入了 act 的异步版本来解决该场景(参考:@987654322 @)。因此,由于异步问题,看起来我无论如何都需要重新测试我的测试,但没有回答为什么我的模拟没有在这个特定场景中使用(使用钩子)。

// /src/Services/UserService.ts
export default class UserService {
    public async getUsers(): Promise<IUser[]> {
        console.debug('Real getUsers');

        const response = await axios.get(https://jsonplaceholder.typicode.com/users);
        return response.data;
    }
}
// /src/Services/__mocks__/UserService.ts
export default class UserService {
    public async getUsers(): Promise<IUser[]> {
        console.debug('Mock getUsers');

        return Promise.resolve([
            { id: 1, name: 'User 1', email: 'email1' },
            { id: 2, name: 'User 2', email: 'email2' },
        ]);
    }
}
import React, { useEffect, useState } from 'react';
import UserService from '../../Services/UserService';
import IHomeState from './IHomeState';
import IUser from '../../Interfaces/IUser';

const Home = (): JSX.Element => {
    const [state, setState] = useState({
        users: [],
    } as IHomeState);

    async function loadData(): Promise<void> {
        const service = new UserService();
        const users = await service.getUsers();

        setState({ users });
    }

    useEffect((): void => { loadData(); }, []);

    const userList = state.users.map((el: IUser): JSX.Element => (
        <li key={el.id}>
            {el.name}
        </li>
    ));

    return (
        <ul>
            {userList}
        </ul>
    );
}

export default Home;
// Test
import React from 'react';
import { shallow } from 'enzyme';
import UserService from '../../Services/UserService';
import Home from './Home';

jest.mock('../../Services/UserService');

it('renders without crashing', (): void => {
    const wrapper = shallow(<Home />);

    expect(wrapper.exists()).toBe(true);
});

【问题讨论】:

    标签: jestjs create-react-app


    【解决方案1】:

    我会首先尝试模拟内联函数以检查您是否正确执行其他所有操作,例如:

    // Test
    import React from 'react';
    import { shallow } from 'enzyme';
    import UserService from '../../Services/UserService';
    import Home from './Home';
    
    const mockedGetUserFunction = async (): Promise<IUser[]> => { /* implement mock */ };
    jest.mock('../../Services/UserService');
    mockedGetUserFunction.bind(UserService);
    
    it('renders without crashing', (): void => {
        const wrapper = shallow(<Home />);
    
        expect(wrapper.exists()).toBe(true);
    });
    

    另外,请尽量避免将您的服务导出为默认值(这需要您在之后调整您的导入):

    export default class UserService => export class UserService
    

    【讨论】:

    • 不行...我添加了逻辑以返回您拥有“实施模拟”的虚假用户列表。测试运行并通过,但它仍然使用真正的服务类,而不是模拟函数。我还更改了服务类,使其不再是默认导出。
    • 嗯,您是否也尝试过删除您在__mocks__ 中制作的模拟?
    • 刚刚试过...同样的结果。如果有帮助,我将我的代码上传到 GitHub,链接在上面的问题中。我觉得我错过了一些非常简单/愚蠢的东西......
    猜你喜欢
    • 2021-12-13
    • 2023-03-13
    • 2018-10-27
    • 1970-01-01
    • 1970-01-01
    • 2018-09-07
    • 1970-01-01
    • 1970-01-01
    • 2019-12-14
    相关资源
    最近更新 更多