When using Sinon stubs and Vue's event system, it appears that the original, stubbed, methods are still being called instead of the stubs themselves. Consider the following example:
import eventBus from '@/utils' // just a simple Vue instance
import Foo from '@/components/Foo'
const initStub = sinon.stub()
const wrapper = shallow(Foo)
wrapper.setMethods({ init: initStub })
eventBus.emit('event that invokes init()')
Foo.init() shouldn't be calledinitStub.called should be trueFoo.init() is calledinitStub.called is falseNotice that the bug (?) doesn't happen if init() is called directly i.e. wrapper.vm.init().
Hm, I'm doubtful that there's a way to fix it. Presumalby, you did something like this:
created () {
eventBus.$on('event that invokes init()', this.init)
}
When you replace the method init after the event has registered, the eventbus doesn't know about it - it still has the old method as the callback for the event listener. And vue-test-utils doesn't know about the event bus, which is not part of the component instance, so it can't "replace" the callback either.
The same would happen if you registered a "normal" event listener (e.g. window.addEventListener('click', this.init), so this would be something that can happen frequently in tests.
The only solution I see it to stub the method immediatly:
const wrapper = shallow(Foo, {
methods: {
init: initStub
}
})
I would not classify this as a bug and rather maybe document this under a headline like "stubbing event listeners set up in created" or something.
Another way to work around this is to wrap the passing function in another one:
created() {
this.bus.$on('event', () => { this.init() })
},
That way the reference to this.init will be determined during runtime.
In my opinion this is no issue in the vue-test-utils and could be closed.
What exactly are you trying to test? Maybe there is a better way to do it.
I'm looking to write some documents about how/what to test for vue-test-utils, knowing what kind of problems people run into and what they are trying to achieve is valuable feedback @phanan .
I'm closing this issue since it won't be fixed, the solution is to use @LinusBorg's suggestion:
const wrapper = shallow(Foo, {
methods: {
init: initStub
}
})
Woot. When I think @LinusBorg's explanation does make a lot of sense, I quickly tried the suggestion and it didn't appear to work. I'll be spending a little more time when I have it, but closing can seem to be a bit too quick.
Most helpful comment
Hm, I'm doubtful that there's a way to fix it. Presumalby, you did something like this:
When you replace the method
initafter the event has registered, the eventbus doesn't know about it - it still has the old method as the callback for the event listener. And vue-test-utils doesn't know about the event bus, which is not part of the component instance, so it can't "replace" the callback either.The same would happen if you registered a "normal" event listener (e.g.
window.addEventListener('click', this.init), so this would be something that can happen frequently in tests.The only solution I see it to stub the method immediatly:
I would not classify this as a bug and rather maybe document this under a headline like "stubbing event listeners set up in
created" or something.