我有一个简单的Vue组件,该组件会在创建API密钥时获取API密钥,并且可以通过单击按钮来更新密钥:
<template>
<div>
<div>{{data.api_key}}</div>
<button ref="refresh-trigger" @click="refreshKey()">refresh</button>
</div>
</template>
<script>
export default {
created() {
axios.get(this.url).then((response) => {
this.data = response.data
})
}
methods: {
refreshKey() {
axios.put(this.url).then((response) => {
this.data = response.data
})
},
}
}
</script>
我想用以下代码对其进行测试:
import {shallowMount} from '@vue/test-utils';
import axios from 'axios';
import apiPage from '../apiPage';
import MockAdapter from 'axios-mock-adapter';
describe('API page', () => {
it('should renew API key it on refresh', async (done) => {
const flushPromises = () => new Promise(resolve => setTimeout(resolve))
const initialData = {
api_key: 'initial_API_key',
};
const newData = {
api_key: 'new_API_key',
};
const mockAxios = new MockAdapter(axios);
mockAxios.onGet('/someurl.json').replyOnce(200, initialData)
mockAxios.onPut('/someurl.json').replyOnce(200, newData);
const wrapper = shallowMount(api);
expect(wrapper.vm.$data.data.api_key).toBeFalsy();
await flushPromises()
wrapper.vm.$nextTick(() => {
expect(wrapper.vm.$data.data.api_key).toEqual(initialData.api_key);
done()
});
wrapper.find({ref: 'refresh-trigger'}).trigger('click');
wrapper.vm.$nextTick(() => {
console.log(mockAxios.history)
expect(wrapper.vm.$data.data.api_key).toEqual(newData.api_key);
expect(mockAxios.history.get.length).toBe(1);
expect(mockAxios.history.get[1].data).toBe(JSON.stringify(initialData));
expect(mockAxios.history.put.length).toBe(1);
done();
});
})
});
但是事实证明,只有get请求被嘲笑了,因为我收到了:
[Vue warn]: Error in nextTick: "Error: expect(received).toEqual(expected)
Difference:
- Expected
+ Received
- new_API_key
+ initial_API_key"
found in
---> <Anonymous>
<Root>
console.error node_modules/vue/dist/vue.runtime.common.dev.js:1883
{ Error: expect(received).toEqual(expected)
更糟糕的是,console.log(mockAxios.history)
返回空的put数组:
{ get:
[ { transformRequest: [Object],
transformResponse: [Object],
timeout: 0,
xsrfCookieName: 'XSRF-TOKEN',
xsrfHeaderName: 'X-XSRF-TOKEN',
maxContentLength: -1,
validateStatus: [Function: validateStatus],
headers: [Object],
method: 'get',
url: '/admin/options/api.json',
data: undefined } ],
post: [],
head: [],
delete: [],
patch: [],
put: [],
options: [],
list: [] }
我试图在describe块中定义mockAxios,并在迭代后用console.log进行记录-事实证明放置请求在此处。但不是在我需要的时候。 :)
我在做什么错?也许有一些方法可以检查是否调用了创建的回调,并且其中的所有异步函数都已完成?也许我使用axios-mock错误?
答案 0 :(得分:0)
此测试代码应通过:
import {shallowMount, createLocalVue} from '@vue/test-utils';
import axios from 'axios';
import api from '@/components/api.vue';
import MockAdapter from 'axios-mock-adapter';
describe('API page', () => {
it('should renew API key it on refresh', async () => {
const flushPromises = () => new Promise(resolve => setTimeout(resolve))
const initialData = {
api_key: 'initial_API_key',
};
const newData = {
api_key: 'new_API_key',
};
const mockAxios = new MockAdapter(axios);
const localVue = createLocalVue();
mockAxios
.onGet('/someurl.json').reply(200, initialData)
.onPut('/someurl.json').reply(200, newData);
const wrapper = shallowMount(api, {
localVue,
});
expect(wrapper.vm.$data.data.api_key).toBeFalsy();
await flushPromises();
expect(wrapper.vm.$data.data.api_key).toEqual(initialData.api_key);
wrapper.find({ref: 'refresh-trigger'}).trigger('click');
await flushPromises();
console.log(mockAxios.history);
expect(wrapper.vm.$data.data.api_key).toEqual(newData.api_key);
expect(mockAxios.history.get.length).toBe(1);
expect(mockAxios.history.put.length).toBe(1);
})
});
一些注意事项:
mockAxios
.onGet('/someurl.json').reply(200, initialData)
.onPut('/someurl.json').reply(200, newData);
mockAxios
.onGet('/anotherUrl.json').reply(200, initialData)
.onPut('/anotherUrl.json').reply(200, newData);
如果要测试仅对端点(使用expect(......get.length).toBe(1)
进行了一次GET调用,则应真正使用reply()
而不是replyOnce()
并对其进行测试您已经在做的方式。 replyOnce()
函数将在第一次回复后删除处理程序,随后的请求中将得到404。
mockAxios.history.get[1].data
将不包含任何内容,原因有3个:GET请求没有正文(仅URL参数),您仅发出1个GET请求(此处您正在检查第二个GET),以及此语句是指已发送的请求,而不是您收到的数据。
您正在使用async/await
功能,这意味着您可以利用$ nextTick的功能:await wrapper.vm.$nextTick();
并放下done()
调用,但是由于您已经拥有flushPromises()
,您也可以使用它。
您无需使用以下代码来测试您在第一个调用中是否收到initialData:
expect(mockAxios.history.get[1].data).toBe(JSON.stringify(initialData));
,因为您已经使用expect(...).toEqual(apiKey)
对其进行了测试。
使用createLocalVue()
实用程序为每个avoid contaminating全局Vue实例的安装创建Vue的本地实例(如果您有多个测试组,则很有用)
最后,是7.最好将此测试分解为多个it
语句;单元测试应该是 micro 测试,即测试小的,可明确识别的行为。尽管我没有为您分解测试,所以它包含的更改尽可能少,但我还是强烈建议您这样做。