我想使用Jest / Jasmine / Enzyme在React中测试事件处理程序。
MyComponent.js :
import React from 'react';
class MyComponent extends React.Component {
constructor(props) {
super(props);
this.clickHandler = this.clickHandler.bind(this);
this.otherMethod = this.otherMethod .bind(this);
}
clickHandler() { this.otherMethod(); }
otherMethod() {}
render() { return <div onClick={this.clickHandler}/>; }
}
export default MyComponent;
MyComponent.test.js :
import React from 'react';
import {mount} from 'enzyme';
import MyComponent from './MyComponent';
it('should work', () => {
const componentWrapper = mount(<MyComponent/>);
const component = componentWrapper.get(0);
spyOn(component, 'otherMethod' ).and.callThrough();
spyOn(component, 'clickHandler').and.callThrough();
componentWrapper.find('div').simulate('click');
expect(component.otherMethod ).toHaveBeenCalled(); // works
expect(component.clickHandler).toHaveBeenCalled(); // does not work
});
尽管我认为我同时监视两个组件方法,但其中一个(对于otherMethod
)有效,而另一个(对于clickHandler
)却没有。我明确我打电话给clickHandler
otherMethod
,如果我不是,toHaveBeenCalled
将被调用,但clickHandler
未被选中以某种方式获得.bind(this)
。为什么呢?
我知道我不必在.and.callThrough()
上使用otherMethod
或otherMethod
,但我同时使用这两种方法同样对待这两种方法并在{上使用它们{1}}实际上不应该有任何区别。
This other SO answer表示我必须在将其作为侦听器附加之前监视函数。如果这是我的问题,那么我就不知道如何解决它:spyOn
语法要求对象该方法是(component
在这种情况下)的属性,但使用{{1需要事先安装component
,这迫使我首先附加监听器。
我的代码使用React可能是相关的(因此我将MyComponent
包含为问号)但不知何故我对此表示怀疑。
答案 0 :(得分:2)
对于这种测试,常见的路径是在组件实例上调用处理程序方法,而不是模拟事件。
您可以确定React团队正在测试onClick
道具,您可以检查“他们”调用您的处理程序时会发生什么。
这也允许你使用浅渲染,至少对我来说要快得多。您可以使用包装器中的instance()
方法轻松获取对实例的引用,然后您可以调用您的处理程序并监视您想要的任何内容。
const wrapper = mount(<MyComponent />)
const instance = wrapper.instance()
instance.clickHandler()
//assert whatever
事实上,可能将你的间谍附加到实例的方法(已经被绑定)也可以。 :)
http://airbnb.io/enzyme/docs/api/ReactWrapper/instance.html
希望它有所帮助!