如何使用 React-Native 和 Jest / Enzyme 在单元测试中访问组件构造函数的变量?



我已经在访问组件构造函数内部的变量来测试使用它的不同方法方面苦苦挣扎了一段时间。 请参阅下面的示例。

我的组件计时器的构造函数。 我想在我的timer.test.js文件中访问countDown

constructor(props){
super(props)
countDown = null,
...
}

下面是我想测试的函数之一(其中使用了coutDown):

pauseTimer(){
this.setState({timerIsActive : false})
clearInterval(countDown)
}

下面是我的timer.test.js文件的示例:

import React from 'react'
import renderer from 'react-test-renderer'
import {shallow} from 'enzyme'

const wrapper = shallow(<Timer/>)
const componentInstance = wrapper.instance()

describe('My timer ', () => {
it('Shallow rendering', () => {
expect(wrapper).toMatchSnapshot()
})
it('Should update state customeTimeValue to 20', ()=>{
componentInstance.setState({...componentInstance.state, customTimeValue : {focus : '20'}})
expect(componentInstance.state.customTimeValue.focus).toEqual('20')
})

it('isValueOutOfRange with 20 should return 20', ()=>{
componentInstance.setState({...componentInstance.state, customTimeValue : {focus : '20'}})
expect(componentInstance.isValueOutOfRange('focus')).toEqual(20)
})
it('isValueOutOfRange with 67 should return 59', ()=>{
componentInstance.setState({...componentInstance.state, customTimeValue : {focus : '67'}})
expect(componentInstance.isValueOutOfRange('focus')).toEqual(59)

我已经搜索了多个帖子和文档,但这些都不是我想要的。我自己尝试过不同的东西,但没有结果。

我希望你们能够帮助我。 谢谢!

根据您的代码,<Timer>使用全局countDown和硬编码配置来表示作业/娱乐间隔。

所以我希望你使用jest.useFakeTimers()来测试这个组件。类似的东西

const wrapper = shallow(<Timer />);
expect(getTime(wrapper)).toEqual('00:00');
expect(modeIsWork(wrapper)).toBeTruthy();
jest.advanceTimersByTime(jobInterval - 1);
expect(getTime(wrapper)).toEqual('04:59');
// should still be in "Work" mode
expect(modeIsWork(wrapper)).toBeTruthy();
jest.advanceTimersByTime(2);
// should get into "Rest" mode
expect(modeIsWork(wrapper)).toBeFalsy(); 
expect(getTime(wrapper)).toEqual('00:00');

其中getTimemodeIsWork是假设的辅助函数,它们使用wrapper.find()和其他酶的方法检查/返回一些。无法访问state,但检查元素的类、属性和内部文本。

回到countDown当前是全局的(不确定是否是故意的)。如果它是全球性的,我们需要确保

const timer1 = shallow(<Timer />);
const timer2 = shallow(<Timer />);
clickPause(timer1);
jest.advanceTimersByTime(1001);
expect(getTime(timer2)).toEqual('00:00'); // second timer is also paused

但我怀疑它偶尔会变得全球性,实际上你需要相反的测试:暂停一个计时器不会停止另一个计时器。

PS在共享计时器中,我还看到decrementTimer依赖于setInterval但没有检查实际时间是否脆弱。虽然计时器漂移似乎在现代浏览器中是固定的,但仍然不能保证计时器将在 1000 毫秒后准确调用。而且由于您每次都无条件地减少内部计数器,这意味着您肯定会越来越晚。为了使解决方案更可靠,您还需要检查当前日期时间并模拟您可能需要类似lolex的东西来模拟setInterval,并以更少的手动工作始终global.Date

感谢您的详细回答。 我设法找到了一些东西来测试我的setInterval是否正常工作(见下文),但现在看来我无法重置假计时器。我已经搜索了文档和帖子,但提供的解决方案对我不起作用。

it('decrementTimer in "focus state" after 1 second should return 4:59', ()=> 
{
jest.useFakeTimers();
componentInstance.setState({...componentInstance.state, timerState : 
'focus'})
expect(componentInstance.state.timer.focus.minutes).toEqual(5);
expect(componentInstance.state.timer.focus.seconds).toEqual(0);
componentInstance.decrementTimer();
jest.advanceTimersByTime(1000);
expect(componentInstance.state.timer.focus.minutes).toEqual(4);
expect(componentInstance.state.timer.focus.seconds).toEqual(59);
jest.useRealTimers();
})
it('decrementTimer in "focus state" after 1 second should return 4:59', ()=> 
{
jest.useFakeTimers();
componentInstance.setState({...componentInstance.state, timer : {
focus : {
minutes : 5,
seconds : 0
}
},
timerState  :'focus'})
expect(componentInstance.state.timer.focus.minutes).toEqual(5);
expect(componentInstance.state.timer.focus.seconds).toEqual(0);
componentInstance.decrementTimer();
jest.advanceTimersByTime(1000);
expect(componentInstance.state.timer.focus.minutes).toEqual(4);
expect(componentInstance.state.timer.focus.seconds).toEqual(59);
jest.useRealTimers();
})

所以在这里我们有两次相同的测试(出于测试目的)。 第一个测试有效,但第二个测试无效,因为在调用setInterval后,它实际上减少了 2 秒(而不是提前提到的 TimersByTime)见下文:

expect(received).toEqual(expected) // deep equality
Expected: 59
Received: 58
158 |             jest.advanceTimersByTime(1000);
159 |             expect(componentInstance.state.timer.focus.minutes).toEqual(4);
> 160 |             expect(componentInstance.state.timer.focus.seconds).toEqual(59);
|                                                                 ^
161 |             jest.useRealTimers();
162 |         })
163 | 
at Object.toEqual (timer.test.js:160:65)

所以我想有两个计时器同时运行。 完成这项工作将解决我最初的问题。 谢谢!

最新更新