2017-02-04 75 views
0

我無法在任何地方找到合適的答案。我希望它不是重複的。 我有一個簡單的酶測試腳本來模擬我在ES6語法中使用Reactjs編寫的表單提交。我正在使用摩卡作爲我的測試跑步者。當我嘗試模擬表單的「提交」時,onSubmit函數未被調用。 我的js文件,我是測試:onsubmit的酶表格沒有被調用

import React, { Component } from 'react'; 
import logo from './logo.svg'; 
import './App.css'; 

class App extends Component { 
    constructor() { 
     super(); 
     this.onSubmitDetails = this.onSubmitDetails.bind(this); 
    }; 

    onSubmitDetails(event) { 
     event.preventDefault(); 
     alert("Hey! Form submitted??") 
    } 
    render() { 
    return (
     <div className="App"> 
      <form onSubmit={this.onSubmitDetails}> 
       <input type="text" className="loginBox" placeholder="Username" 
       required="required"/> 
       <input type="password" className="loginBox" placeholder="Password" required="required"/> 
       <input type="submit" className="loginBox submit" value="SIGN IN"/> 
      </form> 
     </div> 
    ); 
    } 
} 

export default App; 

我的測試代碼:

import 'jsdom-global/register'; 
import React from 'react'; 
import ReactDOM from 'react-dom'; 
import { shallow, mount } from "enzyme"; 
import expect from 'expect'; 
import sinon from 'sinon'; 
import App from './App'; 

describe("Component: LoginContainer",() => { 
it('should login',() => { 
    const props = { 
     fields: { 
      user: { 
       username: {}, 
       password: {} 
      } 
     }, 
     onSubmitDetails:() => {} 
    }; 
    const onSubmitDetails = sinon.spy(); 
    const wrapper = mount(<LoginContainer />); 

    const username = wrapper.find('.loginBox').get(0); 
    username.value = 'abc'; 
    expect(username.value).toEqual('abc'); 

    const password = wrapper.find('.loginBox').get(1); 
    password.value = 'xyz'; 
    expect(password.value).toEqual('xyz'); 

    wrapper.find('form').simulate('submit', { preventDefault(){} }); 
    console.log(onSubmitDetails.called); //gives false 
    }); 
}); 

回答

0

在你粘貼form是在App成分,但你的測試安裝LoginContainer的代碼。讓我們假設這是一個錯字,並且您的測試的確在安裝App。 :)

您正在創建一個間諜,但您需要將它作爲道具傳遞給您的組件,然後在您的內部方法中調用該道具。你幾乎已經在測試中定義了你的道具,但忘了將它們傳遞給你的組件。

取決於你想測試什麼:提交表單調用從外部提供給你的組件的功能(通過prop)?然後接受,作爲一個道具,並調用該函數在代碼:

class App extends Component { 
    constructor() { 
     super(); 
     this.onSubmitDetails = this.onSubmitDetails.bind(this); 
    }; 

    onSubmitDetails(event) { 
     event.preventDefault(); 
     //this prop is what you will fake in your test 
     this.props.login() 
    } 
    render() { 
    return (
     <div className="App"> 
      <form onSubmit={this.onSubmitDetails}> 
      ... 
      </form> 
     </div> 
    ); 
    } 
} 

然後在您的測試,提供您的間諜爲login道具:

it('should login',() => { 
    //the login prop spy 
    const loginSpy = sinon.spy() 
    const props = { 
     fields: { 
      user: { 
       username: {}, 
       password: {} 
      } 
     }, 
     login: loginSpy 
    }; 
    const onSubmitDetails = sinon.spy(); 

    //your code is in App component but you were mouting a LoginContainer?? 
    const wrapper = mount(<App { ...props } />); 

    const username = wrapper.find('.loginBox').get(0); 
    //these two lines are non sense 
    username.value = 'abc'; 
    expect(username.value).toEqual('abc'); 

    const password = wrapper.find('.loginBox').get(1); 
    // the following two as well 
    password.value = 'xyz'; 
    expect(password.value).toEqual('xyz'); 

    // this is where you test your submit event will be calling 
    // whatever functions is passed as `login` prop 
    wrapper.find('form').simulate('submit', { preventDefault(){} }); 
    console.log(loginSpy.called); 
    }); 
}); 
+0

這對我有效!謝謝:) – morghulis

0

既然你正試圖存根裏面的方法您嘗試測試的組件,上面的存根將不起作用。 試試這可能會有所幫助。我認爲App和LoginComponent是相同的。

import 'jsdom-global/register'; 
    import React from 'react'; 
    import ReactDOM from 'react-dom'; 
    import { shallow, mount } from "enzyme"; 
    import expect from 'expect'; 
    import sinon from 'sinon'; 
    import App from './App'; 

    describe("Component: LoginContainer",() => { 
     const props = { 
      fields: { 
       user: { 
        username: {}, 
        password: {} 
       } 
      }, 
     }; 
     const wrapper = mount(<App />); 
     before(() => { 
      sinon.stub(App.prototype, 'onSubmitDetails'); // this will stub the method inside app component 
     }) 

     it('should login',() => { 



     const username = wrapper.find('.loginBox').get(0); 
     username.value = 'abc'; 
     expect(username.value).toEqual('abc'); 

     const password = wrapper.find('.loginBox').get(1); 
     password.value = 'xyz'; 
     expect(password.value).toEqual('xyz'); 

     wrapper.find('form').simulate('submit', { preventDefault(){} }); 
      expect(App.prototype.onSubmitDetails).to.have.property('callCount', 1); //test your expectation here 
     }); 

     after(() => { 
      App.prototype.onSubmitDetails.restore(); // restores stubbed method 
     }); 
    }); 
+0

在我的實際代碼中,我的

位於組件中,比如,它是的子組件。如: ... 。如何訪問現在位於中的onSubmitDetails而不是? – morghulis

+0

這個概念是,如果我們正在測試某個組件,並且需要監視componentWillMount,componentDidMount或該組件內的其他方法等組件內部的函數,那麼我們應該使用上述方法。如果我們將函數作爲道具傳遞給正在測試的組件,那麼我們可以像'const onSubmitDetails = sinon.spy();'一樣創建間諜,並將它傳遞給組件。仔細研究你的問題,onSubmitDetails在組件中,所以你可以嘗試上面的方法,或者在app的formComponent中傳遞函數作爲道具,並按照@charlie的建議進行測試 – duwalanise