After lots of research, it looks like this isn't really possible. If you do them in a very specific format, you can use certain mocking things, but you have to do several things which would be non-standard in your "real" code. I'm not a fan of modifying code for tests.
An alternative that I've settled on is for certain cases, I would just find the element after a mount(), get the property that provides the callback, and then trigger that directly and do whatever I need. Not a perfectly universal scenario, but it works.
Take this example code:
// Parent.js
export default class Parent extends React.Component {
doSomething() {
this.props.doSomethingTriggered();
}
render() {
return <div>
<Child onClick={ this.doSomething.bind() }/>
</div>;
}
}
I can use enzyme to mount the component, then trigger the onClick property of Child and spy on the callback I gave it to ensure it was called properly.
it('should do something', () => {
const callback = sinon.spy(() => {});
const wrapper = mount(<Parent doSomethingTriggered={ callback }/>);
wrapper.find(Child).props().onClick();
sinon.assert.calledOnce(callback);
});
Not quite mocking, but does let me bypass a good chunk of dependent code in certain scenarios.
Since this is a popular question, an update for Enzyme 16, it is now possible. You can now call instance() on any element and then call its function directly.
For example, take these examples:
class Parent extends React.Component {
render() {
return <div><Child /></div>
}
}
class Child extends React.Component {
render() { return <div>Hi</div> }
doSomething() { }
}
With Enzyme 16, you can now do:
mount(<Parent />).find(Child).instance().doSomething()