Currently, to stub methods on a component you need to do this:
const wrapper = mount(TestComponent)
wrapper.vm.clickHandler = sinon.stub() // Stub the method
wrapper.update() // Force the vm to update
wrapper.find('button').trigger('click')
expect(wrapper.vm.clickHandler.called).to.equal(true)
I think we should either add a method, or an option that stubs component methods:
// Method
const wrapper = mount(TestComponent)
wrapper.stubMethod(clickHandler, sinon.stub()) // Stubs the method and forces update
wrapper.find('button').trigger('click')
expect(wrapper.vm.clickHandler.called).to.equal(true)
It could also be called setMethods, like the setData and setProps methods, and take an object.
// Option
const wrapper = mount(TestComponent, {
stubMethods: { // stubs methods before mount
clickHandler: clickHandlerStub
}
})
wrapper.find('button').trigger('click')
expect(wrapper.vm.clickHandler.called).to.equal(true)
Personally I prefer the stubMethod/ setMethods approach, but I'd like to hear peoples thoughts 馃檪
I previously had a hook that was called before the component was mounted, which exposed a deep copy of the component so you could manually stub it's methods (without affecting the original component). But i actually really like your approach, I think it's really simple.
A couple of thoughts:
{clickHandler:true}I prefer setMethods as it is consistent with setData and setProps. However, I think there should also be a method to retrieve them as it could be confusing that you then have to use the vm to check if it has been called.
wrapper.stubMethod(clickHandler, sinon.stub())
...
expect(wrapper.vm.clickHandler.called).to.equal(true)
With the current way, at least the way you set and get is consistent.
wrapper.vm.clickHandler = sinon.stub()
...
expect(wrapper.vm.clickHandler.called).to.equal(true)
@philefstat
We could recommend this pattern:
const clickHandlerStub = sinon.stub()
wrapper.stubMethod('clickHandler', clickHandlerStub)
...
expect(clickHandlerStub.called).to.equal(true)
Or this:
const clickHandlerStub = sinon.stub()
wrapper.stubMethods({
clickHandler: clickHandlerStub
})
@jackmellis
would you want the option to restore a stubbed method at a later point?
I don't think so, with stubMethod you could save the original before stubbing and then restore it later with the same method.
could you stub a method without having to provide an alternate function {clickHandler:true}
Yes I think that's a good idea
what about computed properties?
Yes I think that a setComputed method would be a good idea if setData does not work for a use case. Would you be able to provide example where setData doesn't work, so I can use it as a test case?
@eddyerburgh those both look great 馃憤
That pattern also allows some of the useful sinon methods to be called on the stub without reaching directly into the vm.
i.e.
clickhandlerStub.resetHistory()
stubMethods could be quite useful for larger components with multiple methods that need to be stubbed.
const methods = {
foo: sinon.stub().returns(3),
bar: sinon.stub(),
baz: sinon.stub().throws("TypeError")
}
wrapper.stubMethods(methods)
...
expect(methods.foo).to.be.calledOnce
expect(methods.bar).to.be.calledTwice
There's now a setMethods method.
We should have a setComputed method too. I've created a new issue for that:
setMethods worked great.
like here:
const spy = jest.spyOn(wrapper.vm, 'handleChange')
wrapper.setMethods({ handleChange: spy })
wrapper.find('.some-input').trigger('change')
expect(spy).toHaveBeenCalled()
Hi All,
const spy = sinon.stub()
wrapper.setMethods({ onClickCreate: spy })
wrapper.find('#btn-create-proposal').trigger('click')
expect(spy.called).toBe(true)
this is not working.
In Actual the method defined in component being mounted is being called.
Thanks for help in advance
Most helpful comment
There's now a
setMethodsmethod.We should have a setComputed method too. I've created a new issue for that:
https://github.com/vuejs/vue-test-utils/issues/55