为啥我不能在这里使用 mockResolvedValue?
Posted
技术标签:
【中文标题】为啥我不能在这里使用 mockResolvedValue?【英文标题】:Why am I unable to use mockResolvedValue here?为什么我不能在这里使用 mockResolvedValue? 【发布时间】:2021-01-06 22:10:42 【问题描述】:我不清楚在使用以下设置时如何模拟我的 api 响应。
我有以下测试:
import React from 'react';
import cleanup, render, wait from '@testing-library/react';
import axios from 'axios';
import Condition from './index.jsx';
jest.mock('axios', () =>
return
create: jest.fn(() => (
get: jest.fn().mockResolvedValue( data: ),
interceptors:
request: use: jest.fn(), eject: jest.fn() ,
response: use: jest.fn(), eject: jest.fn() ,
,
)),
;
);
afterEach(cleanup);
test('fetches and displays data', async () =>
axios.get.mockResolvedValue( data: 'mock data' );
const container = render(<Condition ...props />);
await wait(() => expect(container.textContent).toContain('Current milestone'));
expect(container).toBeDefined();
);
... 以及以下 api 助手:
import axios from 'axios';
const api = axios.create(
baseURL: window.apiPath,
withCredentials: true,
);
api.interceptors.request.use(config =>
const newConfig = Object.assign(, config);
newConfig.headers.Accept = 'application/json';
return newConfig;
, error => Promise.reject(error));
export default api;
我的Condition
组件在挂载时使用以下函数来获取数据:
const fetchAsync = async endpoint =>
const result = await api.get(endpoint);
setSuffixOptions(result.data.data);
console.log('result.data.data', result.data.data);
;
测试中的axios.get.mockResolvedValue( data: 'mock data' );
行导致如下错误:
TypeError: Cannot read property 'mockResolvedValue' of undefined
124 |
125 | test('fetches and displays data', async () =>
> 126 | axios.get.mockResolvedValue( data: 'mock data' );
| ^
127 | const container = render(<Condition ...props />);
128 | await wait(() => expect(container.textContent).toContain('Current milestone'));
129 | expect(container).toBeDefined();
我应该使用不同的方法来模拟响应吗?
编辑
调用axios.create.get.mockResolvedValue( data: 'mock data' );
会导致同样的错误。
【问题讨论】:
因为你的 Axios 测试替身只有一个 create prop,没有 get。 但是create方法是创建api的,它在api文件中有get和interceptors方法。如何为该形状修改axios.get.mockResolvedValue
?
当然,但是您在测试中没有调用它。
调用 axios.create.get.mockResolvedValue( data: 'mock data' );
会导致同样的错误。
axios.create.get
正在尝试访问 get
属性 on 函数,它不会调用函数。
【参考方案1】:
要模拟您的 api 响应,您可以将 jest.spyOn
与 mockImplementation
结合使用,例如如下:
import api from './api';
const mock = jest.spyOn(api,"get");
mock.mockImplementation(() => Promise.resolve( data: ));
在上面的示例中,api.get
方法被替换为模拟返回 data: 'mock data'
的成功调用。
它可以放在你的test
函数中,如下:
test('fetches and displays data', async () =>
const mock = jest.spyOn(api, "get");
mock.mockImplementation(() => Promise.resolve( data: ));
const container = render(<Condition ...props />);
await wait(() => expect(container.textContent).toContain('Current milestone'));
expect(container).toBeDefined();
);
【讨论】:
我会将响应数据传递到哪里? 在 Promise.resolve 中,像这样:mock.mockImplementation(() => Promise.resolve( data: ))
介意在答案中放弃吗?那我就接受了。【参考方案2】:
更好的方法是模拟 ./api
辅助模块而不是 axios
模块。因为您正在测试导入 ./api
作为其直接依赖项的组件。对于组件,axios
模块是间接依赖。如果你想测试./api
helper,那么你应该模拟axios
模块,因为现在它成为./api
的直接依赖。
例如
index.tsx
:
import React, useEffect, useState from 'react';
import api from './api';
function Condition(props)
const [options, setSuffixOptions] = useState();
const fetchAsync = async (endpoint) =>
const result = await api.get(endpoint);
setSuffixOptions(result.data);
console.log('result.data', result.data);
;
useEffect(() =>
fetchAsync('http://localhost:3000/api');
);
return <div>options</div>;
export default Condition;
index.test.tsx
:
import React from 'react';
import Condition from './';
import render, wait from '@testing-library/react';
import api from './api';
import mocked from 'ts-jest/utils';
jest.mock('./api', () =>
return get: jest.fn() ;
);
describe('63981693', () =>
test('fetches and displays data', async () =>
mocked(api.get).mockResolvedValue( data: 'mock data' );
const props = ;
const container = render(<Condition ...props />);
await wait(() => expect(container.textContent).toContain('mock data'));
expect(api.get).toBeCalledWith('http://localhost:3000/api');
expect(container).toBeDefined();
);
);
我们不关心./api
模块的实现,因为我们已经模拟了它。
带有覆盖率报告的单元测试结果:
PASS src/***/63981693/index.test.tsx (12.377s)
63981693
✓ fetches and displays data (68ms)
console.log src/***/63981693/index.tsx:1461
result.data mock data
console.log src/***/63981693/index.tsx:1461
result.data mock data
-----------|----------|----------|----------|----------|-------------------|
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s |
-----------|----------|----------|----------|----------|-------------------|
All files | 100 | 100 | 100 | 100 | |
index.tsx | 100 | 100 | 100 | 100 | |
-----------|----------|----------|----------|----------|-------------------|
Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshots: 0 total
Time: 14.873s, estimated 18s
【讨论】:
你在这里使用ts-jest
,但项目不是用打字稿写的。以上是关于为啥我不能在这里使用 mockResolvedValue?的主要内容,如果未能解决你的问题,请参考以下文章
为啥我不能成功使用 composer require packageName?