如何正确模拟ES6类依赖项

时间:2019-07-26 13:45:15

标签: jestjs create-react-app

我正在努力使模拟能够为我的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的异步版本来解决该情况( ref:https://github.com/facebook/react/issues/14050#issuecomment-480272261)。因此,由于异步问题,我似乎仍然需要重新测试,但无法回答为什么在这种特殊情况下(使用挂钩)未使用我的模拟游戏。

// /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);
});

1 个答案:

答案 0 :(得分:0)

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

// 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