2016-11-15 82 views
1

我有以下智能组件使用componentWillMount生命周期方法进行异步调用来获取数据。我正在为它编写测试,但我无法测试该函数是否被调用,以及它是否在组件被装载之前被调用。它们是重要的案例。如何在已连接的React-Redux组件中测试componentWillMount?

为智能型组件的代码如下:

const mapStateToProps = (state) => { const context = state.context; return { 
    isError: context.error, }; }; 

const options = { componentWillMount: (props) => { 
    const { dispatch } = props; 
    dispatch(fetchContextUser()); }, }; 

export function App(props) { return (
    <div className="app"> 
     { props.isError ? (<ContextError />) : (<Main />) } 
     { props.children } 
    </div> ); } 

App.propTypes = { children: PropTypes.object, // eslint-disable-line react/forbid-prop-types isError: PropTypes.bool.isRequired, // eslint-disable-line react/forbid-prop-types }; 

export default connect(mapStateToProps, null)(functional(App, options)); 

我使用的酶,柴等模拟适配器,用于测试该组件。测试块如下:

describe.only('Render Connected Component',() => { let store; beforeEach(() => { 
    store = mockStore({ 
     context: { 
     error: false, 
     }, 
    }); }); it('Should render connected components',() => { 
    const connectedWrapper = mount(
     <Provider store={store}> 
     <ConnectedApp /> 
     </Provider> 
    ); 
    expect(connectedWrapper).to.be.present(); }); }); 

我只是想测试两件事情:

1)fetchContextUser被称为 2)fetchContextUser被称为组件被安装之前

回答

0

我觉得@佩德罗 - jiminez是接近,但在这里失去了两个元素:在酶

  • 为了在调用componentWillMount,你需要使用mount,不shallow
  • 这个回答假定fetchContextUser是一个道具,可以用间谍来代替。在这种情况下,您可能希望在测试中存在store.dispatch,并断言它是使用fetchContextUser调用的,假设这只是一个纯函数。

所以测试会是什么样子:

describe.only('Render Connected Component',() => { 
    let store; 
    beforeEach(() => { 
    store = mockStore({ 
     context: { 
     error: false, 
     }, 
    }); 
    // stub dispatch 
    sinon.stub(store.dispatch); 
    }); 
    it('Should render connected components',() => { 
    const connectedWrapper = mount(
     <Provider store={store}> 
     <ConnectedApp /> 
     </Provider> 
    ); 
    expect(connectedWrapper).to.be.present(); 
    // Now test dispatch called 
    expect(store.dispatch.calledOnce).to.be.true; 
    expect(store.dispatch.args[0][0]).to.deepEqual(fetchContextUser()); 
    }); 
}); 
0

我认为你只需要测试componentWillMount方法调用fetchContextUser的动作,因为你必须相信ReactJS会调用componentWillMount方法在安装之前,所以,这个前提测试你的第二种情况。 因此,为了测试我觉得你可以做这样的事情在第一种情况:

import sinon from 'sinon'; 
... 

it('It calls fetchContextUser when calls componentWillMount',() => { 
    const fetchContextUserSpy = sinon.spy(); 
    const wrapper = shallow(<App fetchContextUser={fetchContextUserSpy} />); 
    fetchContextUserSpy.reset(); //reset the spy to avoid unwanted calls 
    wrapper.instance().componentWillMount(); // Call componentWillMount directly 
    expect(fetchContextUserSpy.calledOnce).to.be.true; // Expect that after call componentWillMount() the fetchContextUserSpy was called once 

在这个测试中,你只需要直接调用componentWillMount()函数,并预计,fetchContextUserSpy被调用,从而使测试你的情况1。 我使用sinon.js来测试何时调用函数。

再次您壳体2不需要进行测试,因为ReactJS保证了部件安装前的componentWillMount方法被调用。

============================================== ===========================

与功能组件试试这个

it('It calls fetchContextUser when mounted',() => { 
    const fetchContextUserSpy = sinon.spy(); 
    const wrapper = shallow(<App fetchContextUser={fetchContextUserSpy} />); 
    expect(fetchContextUserSpy.calledOnce).to.be.true; // Expect that the component calls the fetchContextUserSpy 
}); 
+0

另外,我得到一个错误,** wrapper.instance(...)componentWillMount不是一个函数**。 –

+0

这可能是因为你的组件是一个**功能组件**,并且这种组件不能访问** componentWillMount **或任何**生命周期方法**。 –

+0

是的,它是一个功能组件。有没有机会解决这个问题? –