问题描述
我一直在与一个新团队合作开发一个React应用,讨论围绕编写针对window.scroll事件上触发方法的组件的单元测试进行.
I have been working on a React app with a new team and the discussion came up around writing unit tests for components that trigger methods on window.scroll events.
所以,让我们以这个组件为例.
So, let's take this component as an example.
import React, { Component } from 'react';
class MyComponent extends Component {
componentDidMount() {
window.addEventListener('scroll', this.props.myScrollMethod);
}
componentWillUnmount() {
window.removeEventListener('scroll', this.props.myScrollMethod);
}
render() {
return (
<div>
<h1>Hello MyComponent!</h1>
</div>
)
};
};
export default MyComponent;
如您所见,我正在采用一种方法,该方法通过prop传递到组件中,并将其绑定到窗口事件侦听器,其中事件为scroll
.在现实世界中,当用户向下滚动页面时,此组件将调用myScrollMethod
(让我们假设这里的用例是当用户滚动超过页面上的某个点时显示粘性导航栏).
As you can see, I am taking a method which is passed into the component via a prop and binding it to the window event listener, where the event is scroll
. In the real world this component would call myScrollMethod
as the user is scrolling down a page (let's assume the use case here is to show a sticky navigation bar when the user has scrolled beyond a certain point on the page).
问题是...我需要找到一种合适的方法进行测试.我的最终目标是创建一个间谍方法,该方法通过myScrollMethod
道具传递到组件中,然后触发滚动(或在测试中模拟滚动),最后断言滚动处理程序方法是否已触发.这是我的尝试:
The problem is...I need to find a suitable way of testing this. My end goal is to create a spy method which is passed into the component via the myScrollMethod
prop, then trigger a scroll (or mock a scroll in the test) and finally assert whether the scroll handler method has fired or not. Here is my attempt at this:
import React from 'react';
import sinon from 'sinon';
import expect, { createSpy } from 'expect';
import { shallow } from 'enzyme';
import MyComponent from './MyComponent';
describe('The <MyComponent /> component', () => {
let onScroll;
let MyTestComponent;
beforeEach(() => {
onScroll = createSpy();
MyTestComponent = shallow(
<MyComponent
myScrollMethod={onScroll}
/>
);
});
it('Should call the onScroll method when a user scrolls', () => {
expect(onScroll).toNotHaveBeenCalled();
window.dispatchEvent(new window.UIEvent('scroll', { detail: 0 }));
expect(onScroll).toHaveBeenCalled();
});
});
我遇到的问题是最终断言失败了,因为从未调用过间谍.我还提到了该网站上的许多其他帖子,但是到目前为止,还没有找到合适的解决方案.任何建议将不胜感激,因为它已经困扰了我一阵子!
The issue that I am having is that the final assertion is failing because the spy is never called. I've referred to a number of other posts on this site but so far have not found a suitable solution. Any suggestions would be greatly appreciated as it's been racking my brain for a while now!
非常感谢!
推荐答案
不幸的是,我认为酶在这里不会有太大帮助.该库仅处理React的综合事件系统中的事件.因此,使用Enzyme渲染的组件无法与添加到窗口中的事件侦听器一起使用. 有关酶github的问题提供了更多详细信息,并提出了一些建议可能对您有帮助的解决方法.
Unfortunately, I don't think Enzyme is going to be much help here. The library only handles events within React's synthetic event system. So a component you render with Enzyme is not going to work with event listeners added to the window. This issues thread on Enzyme's github gives more details and there are some suggested workarounds that might help you.
例如,您可能想要监视window.addEventListener
,然后可以在挂载上检查是否已使用参数"scroll"
和回调函数调用了它.
For example, you might want to spy on window.addEventListener
, then you can check on mount that it was called with the arguments "scroll"
and your callback.
关于您的特定代码,在componentDidMount
中设置了滚动侦听器,但是您的组件呈浅色显示,因此实际上并未调用componentDidMount
(因此没有侦听器).尝试将此行添加到您的beforeEach
:MyTestComponent.instance().componentDidMount()
Regarding your specific code, the scroll listener is set in componentDidMount
but your component is shallow rendered, so componentDidMount
isn't actually called (so there is no listener). Try adding this line to your beforeEach
: MyTestComponent.instance().componentDidMount()
这篇关于用酶测试“窗口滚动事件处理程序"的最佳方法是什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!