繁体   English   中英

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

[英]How to access the variable of a component constructor within unit tests with React-Native and Jest / Enzyme?

现在,我一直在努力尝试访问组件构造函数内部的变量,以测试使用它的不同方法。 请参见下面的示例。

我的组件Timer的构造函数。 我想在我的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但没有检查实际时间是否脆弱。 尽管定时器偏移在现代浏览器中似乎是固定的,但仍不能保证定时器将在1000ms之后精确调用。 而且由于您每次都无条件递减内部计数器,这意味着您肯定会越来越晚。 为了使解决方案更可靠,您还需要检查当前的日期时间并进行模拟,可能需要lolex类的lolex来模拟setIntervalglobal.Date ,而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的被调用后,它实际上是由2secs(如advanceTimersByTime提到的,而不是由一个)请参见下面递减:

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)

因此,我想有两个计时器同时运行。 进行这项工作可以解决我最初的问题。 谢谢 !

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM