我正在尝试重构一个单元测试,以将使用 axios 调用 API 的服务与调用该服务的组件隔离开来。
该服务目前非常简单:
import axios from 'axios'
export default class SomeService {
getObjects() {
return axios.get('/api/objects/').then(response => response.data);
}
}
这是调用服务的组件的片段:
const someService = new SomeService();
class ObjectList extends Component {
state = {
data: [],
}
componentDidMount() {
someService.getObjects().then((result) => {
this.setState({
data: result,
});
});
}
render() {
// render table rows with object data
}
}
export default ObjectList
我可以通过模拟 axios 来测试 ObjectList 是否按照我的预期呈现数据:
// ...
jest.mock('axios')
const object_data = {
data: require('./test_json/object_list_response.json'),
};
describe('ObjectList', () => {
test('generates table rows from object api data', async () => {
axios.get.mockImplementationOnce(() => Promise.resolve(object_data));
const { getAllByRole } = render(
<MemoryRouter>
<table><tbody><ObjectList /></tbody></table>
</MemoryRouter>
);
await wait();
// test table contents
});
});
一切都过去了,没有问题。作为一个主要的学术练习,我试图弄清楚如何模拟 SomeService 而不是 axios,这就是事情出错的地方,因为我认为我对传递的内容的内部了解不够。
例如,我想既然 SomeService 只返回 axios 响应,我可以类似地模拟 SomeService,有点像这样:
// ...
const someService = new SomeService();
jest.mock('./SomeService')
const object_data = {
data: require('./test_json/object_list_response.json'),
};
describe('ObjectList', () => {
test('generates table rows from object api data', async () => {
someService.getObjects.mockImplementationOnce(() => Promise.resolve(object_data))
// etc.
这失败并出现错误:Error: Uncaught [TypeError: Cannot read property 'then' of undefined]
,并且错误可追溯到以下行ObjectList
:
someService.getObjects().then((result) => {
我具体需要模拟ObjectList
什么,以便组件可以获得SomeService
设置其状态所需的内容?