在单元测试中使用模拟提取响应时,Vue 组件无法呈现
Vue component fails to render when using mocked fetch response in unit test
我想测试 BootstrapVue table 是否根据 API 提供的数据正确呈现。作为其中的一部分,我模拟了 fetch
函数。当我使用 loadItems()
方法静态提供数据时,它工作正常 - 呈现 3 行。但是当我改为使用 API 调用方法 getData()
时 - 行未呈现。
fetch
的模拟似乎在成功记录 API 响应时起作用,但它似乎没有进入 Vue 组件的数据选项。
要测试的Vue组件:
// MenuTable.vue
<template>
<div>
<b-table class="table"
:items="items" :fields="fields">
</b-table>
</div>
</template>
<script>
export default {
methods: {
getData() {
fetch('https://www.myexampleapi.com/menu', {
method: 'GET',
mode: 'cors',
})
.then((response) => response.json())
.then((data) => {
console.log(data);
this.items = data;
})
.catch((error) => {
this.error = error.message;
console.log(error);
});
},
loadItems() {
return [
{ cost: 10, food: 'Spaghetti' },
{ cost: 20, food: 'Pizza' },
{ cost: 30, food: 'Hamburger' },
];
},
},
created() {
this.items = this.loadItems(); // load items statically
this.getData(); // load items from API
},
data() {
return {
fields: ['food', 'cost'],
items: [],
};
},
};
</script>
测试文件:
// MenuTable.spec.js
import { mount, createLocalVue } from '@vue/test-utils';
import MenuTable from '@/components/MenuTable.vue';
// eslint-disable-next-line no-unused-vars
import { BootstrapVue, BButton, BTable, BRow } from 'bootstrap-vue';
// create an extended `Vue` constructor
const localVue = createLocalVue();
// install plugins as normal
localVue.use(BootstrapVue);
describe('Table.vue Buttons Test', () => {
let wrapper = null;
// SETUP - run before to each unit test
beforeEach(() => {
global.fetch = jest.fn(() => Promise.resolve({
json: () => Promise.resolve([
{ cost: 10, food: 'Spaghetti' },
{ cost: 20, food: 'Pizza' },
{ cost: 30, food: 'Hamburger' },
]),
}));
// render the component
wrapper = mount(MinimalTable, {
localVue,
});
});
// TEARDOWN - run after to each unit test
afterEach(() => {
jest.resetModules();
jest.clearAllMocks();
jest.restoreAllMocks();
wrapper.destroy();
});
it('renders three rows', () => {
const tableComponent = wrapper.findAll('tbody > tr');
console.log(tableComponent.length);
expect(tableComponent.length).toEqual(3);
});
});
我已经通过使用 mount
来确保这不是 shallow mounting 的情况,而且我想我已经确保测试等待 API 的响应使用 Promises 响应。
为什么可以记录 API 响应数据,但没有分配给 items
数据变量?
您似乎希望 Jest 自动等待 Promise
s,但实际上您必须明确地这样做。当 fetch
的 Promise
解决时,您可以等待 setTimeout()
没有指定延迟的下一个宏滴答:
it('renders three rows', async () => {
// wait macro tick when `fetch` Promises resolve
await new Promise(r => setTimeout(r))
const tableComponent = wrapper.findAll('tbody > tr');
console.log(tableComponent.length);
expect(tableComponent.length).toEqual(3);
})
我想测试 BootstrapVue table 是否根据 API 提供的数据正确呈现。作为其中的一部分,我模拟了 fetch
函数。当我使用 loadItems()
方法静态提供数据时,它工作正常 - 呈现 3 行。但是当我改为使用 API 调用方法 getData()
时 - 行未呈现。
fetch
的模拟似乎在成功记录 API 响应时起作用,但它似乎没有进入 Vue 组件的数据选项。
要测试的Vue组件:
// MenuTable.vue
<template>
<div>
<b-table class="table"
:items="items" :fields="fields">
</b-table>
</div>
</template>
<script>
export default {
methods: {
getData() {
fetch('https://www.myexampleapi.com/menu', {
method: 'GET',
mode: 'cors',
})
.then((response) => response.json())
.then((data) => {
console.log(data);
this.items = data;
})
.catch((error) => {
this.error = error.message;
console.log(error);
});
},
loadItems() {
return [
{ cost: 10, food: 'Spaghetti' },
{ cost: 20, food: 'Pizza' },
{ cost: 30, food: 'Hamburger' },
];
},
},
created() {
this.items = this.loadItems(); // load items statically
this.getData(); // load items from API
},
data() {
return {
fields: ['food', 'cost'],
items: [],
};
},
};
</script>
测试文件:
// MenuTable.spec.js
import { mount, createLocalVue } from '@vue/test-utils';
import MenuTable from '@/components/MenuTable.vue';
// eslint-disable-next-line no-unused-vars
import { BootstrapVue, BButton, BTable, BRow } from 'bootstrap-vue';
// create an extended `Vue` constructor
const localVue = createLocalVue();
// install plugins as normal
localVue.use(BootstrapVue);
describe('Table.vue Buttons Test', () => {
let wrapper = null;
// SETUP - run before to each unit test
beforeEach(() => {
global.fetch = jest.fn(() => Promise.resolve({
json: () => Promise.resolve([
{ cost: 10, food: 'Spaghetti' },
{ cost: 20, food: 'Pizza' },
{ cost: 30, food: 'Hamburger' },
]),
}));
// render the component
wrapper = mount(MinimalTable, {
localVue,
});
});
// TEARDOWN - run after to each unit test
afterEach(() => {
jest.resetModules();
jest.clearAllMocks();
jest.restoreAllMocks();
wrapper.destroy();
});
it('renders three rows', () => {
const tableComponent = wrapper.findAll('tbody > tr');
console.log(tableComponent.length);
expect(tableComponent.length).toEqual(3);
});
});
我已经通过使用 mount
来确保这不是 shallow mounting 的情况,而且我想我已经确保测试等待 API 的响应使用 Promises 响应。
为什么可以记录 API 响应数据,但没有分配给 items
数据变量?
您似乎希望 Jest 自动等待 Promise
s,但实际上您必须明确地这样做。当 fetch
的 Promise
解决时,您可以等待 setTimeout()
没有指定延迟的下一个宏滴答:
it('renders three rows', async () => {
// wait macro tick when `fetch` Promises resolve
await new Promise(r => setTimeout(r))
const tableComponent = wrapper.findAll('tbody > tr');
console.log(tableComponent.length);
expect(tableComponent.length).toEqual(3);
})