我正试图在debounced方法中测试一个axios调用,但是如果我添加假定时器,moxios.wait()总是超时。 如果将去抖时间设置得足够小(例如10ms),则测试在没有时钟的情况下工作,但这无助于测试正确的去抖动。 我已经尝试过试验Vue.nextTick以及回调它()async,但我似乎只是进入了杂草。什么是正确的方法?
这是一个组件和测试合二为一,显示了问题:
import Vue from 'vue'
import { mount } from 'vue-test-utils'
import axios from 'axios'
import moxios from 'moxios'
import _ from 'lodash'
import expect from 'expect'
import sinon from 'sinon'
let Debounced = Vue.component('Debounced',
{
template: `<div><button @click.prevent="fetch"></button></div>`,
data() {
return {
data: {}
}
},
methods: {
fetch: _.debounce(async () => {
let data = await axios.post('/test', {param: 'example'})
this.data = data
}, 100)
}
}
)
describe.only ('Test axios in debounce()', () => {
let wrapper, clock
beforeEach(() => {
clock = sinon.useFakeTimers()
moxios.install()
wrapper = mount(Debounced)
})
afterEach(() => {
moxios.uninstall()
clock.restore()
})
it ('should send off a request when clicked', (done) => {
// Given we set up axios to return something
moxios.stubRequest('/test', {
status: 200,
response: []
})
// When the button is clicked
wrapper.find('button').trigger('click')
clock.tick(100)
moxios.wait(() => {
// It should have called axios with the right params
let request = moxios.requests.mostRecent()
expect(JSON.parse(request.config.data)).toEqual({param: 'example'})
done()
})
})
})
答案 0 :(得分:1)
关于测试超时异常: moxios.wait
依赖于setTimeout
,但我们将setTimeout
替换为自定义js实现,并制作了moxios.wait
工作,我们应该在等待调用后调用clock.tick(1)
。
moxios.wait(() => {
// It should have called axios with the right params
let request = moxios.requests.mostRecent()
expect(JSON.parse(request.config.data)).toEqual({param: 'example'})
done()
});
clock.tick(1);
这将允许测试进入回调主体...但是它将再次失败,除非未定义request
。
主要问题:问题是假计时器正在同步调用所有回调(不使用macrotask事件循环),但是Promises仍使用事件循环。
因此,您的代码仅在执行任何Promise“ then”之前结束。当然,您可以将测试代码作为微任务推送来访问请求和响应数据,例如(使用await
或将其包装为“回调”)
wrapper.find('button').trigger('click');
// debounced function called
clock.tick(100);
// next lines will be executed after an axios "then" callback where a request will be created.
await Promise.resolve();
// axios promise created, a request is added to moxios requests
// next "then" is added to microtask event loop
console.log("First assert");
let request = moxios.requests.mostRecent()
expect(JSON.parse(request.config.data)).toEqual({ param: 'example' });
// next lines will be executed after promise "then" from fetch method
await Promise.resolve();
console.log("Second assert");
expect(wrapper.vm.data.data).toEqual([]);
done();
我为数据添加了另一个断言,以表明您的代码应“等待”两个“ then”回调:axios内部“ then”与您的请求创建以及您的{then}从fetch
方法。
如您所见,我删除了wait
呼叫,因为如果您要等待Promises,它实际上什么也没做。
是的,这是一个肮脏的hack,与axios实现本身密切相关,但是我没有更好的建议,首先我只是试图解释这个问题。