クラスプロパティのテストを解決するためのさまざまな提案を見て成功していませんでしたが、間違っている可能性がある場所に誰かがもう少し光を当てることができるかどうか疑問に思っていました。関数が呼び出されましたが、呼び出されませんでした。
Search.jsx
import React, { Component } from 'react'
import { func } from 'prop-types'
import Input from './Input'
import Button from './Button'
class SearchForm extends Component {
static propTypes = {
toggleAlert: func.isRequired
}
constructor() {
super()
this.state = {
searchTerm: ''
}
this.handleSubmit = this.handleSubmit.bind(this)
}
handleSubmit = () => {
const { searchTerm } = this.state
const { toggleAlert } = this.props
if (searchTerm === 'mocky') {
toggleAlert({
alertType: 'success',
alertMessage: 'Success!!!'
})
this.setState({
searchTerm: ''
})
} else {
toggleAlert({
alertType: 'error',
alertMessage: 'Error!!!'
})
}
}
handleChange = ({ target: { value } }) => {
this.setState({
searchTerm: value
})
}
render() {
const { searchTerm } = this.state
const btnDisabled = (searchTerm.length === 0) === true
return (
<div className="well search-form soft Push--bottom">
<ul className="form-fields list-inline">
<li className="flush">
<Input
id="search"
name="search"
type="text"
placeholder="Enter a search term..."
className="text-input"
value={searchTerm}
onChange={this.handleChange}
/>
<div className="feedback Push-half--right" />
</li>
<li className="Push-half--left">
<Button className="btn btn--positive" disabled={btnDisabled} onClick={this.handleSubmit}>
Search
</Button>
</li>
</ul>
</div>
)
}
}
export default SearchForm
最初のオプション:
it('should call handleSubmit function on submit', () => {
const wrapper = shallow(<Search toggleAlert={jest.fn()} />)
const spy = jest.spyOn(wrapper.instance(), 'handleSubmit')
wrapper.instance().forceUpdate()
wrapper.find('.btn').simulate('click')
expect(spy).toHaveBeenCalled()
spy.mockClear()
})
2番目のオプション:
it('should call handleSubmit function on submit', () => {
const wrapper = shallow(<Search toggleAlert={jest.fn()} />)
wrapper.instance().handleSubmit = jest.fn()
wrapper.update()
wrapper.find('.btn').simulate('click')
expect(wrapper.instance().handleSubmit).toHaveBeenCalled()
})
クラスプロパティを使用すると、関数は関数を登録するためにコンポーネントを更新する必要があるクラスのインスタンスですが、モックではなくコンポーネントのhandleSubmit関数が呼び出されるように見えますか?
HandleSubmitをメソッドとしてクラス関数にスワップすると、Search.prototypeをスパイするときにテストに合格するクラスプロトタイプにアクセスできますが、クラスプロパティアプローチのソリューションを取得したいのです。
すべての提案と推奨事項に感謝します!
望ましくないコードのケースが変更された場合、ユニットテストはerror
をキャッチするのに十分な堅牢性を備えている必要があります。
テストに厳格なアサーションを含めてください。
条件ステートメントについては、ブランチもカバーしてください。たとえば、if
およびelse
ステートメントの場合、two
テストを作成する必要があります。
ユーザーアクションの場合は、関数を手動で呼び出すのではなく、アクションをシミュレートする必要があります。
以下の例をご覧ください。
import React from 'react';
import { shallow } from 'enzyme';
import { SearchForm } from 'components/Search';
describe('Search Component', () => {
let wrapper;
const toggleAlert = jest.fn();
const handleChange = jest.fn();
const successAlert = {
alertType: 'success',
alertMessage: 'Success!!!'
}
const errorAlert = {
alertType: 'error',
alertMessage: 'Error!!!'
}
beforeEach(() => {
wrapper = shallow(<SearchForm toggleAlert={toggleAlert} />);
});
it('"handleSubmit" to have been called with "mocky"', () => {
expect(toggleAlert).not.toHaveBeenCalled();
expect(handleChange).not.toHaveBeenCalled();
wrapper.find('Input').simulate('change', { target: { value: 'mocky' } });
expect(handleChange).toHaveBeenCalledTimes(1);
expect(wrapper.state().searchTerm).toBe('mocky');
wrapper.find('Button').simulate('click');
expect(toggleAlert).toHaveBeenCalledTimes(1);
expect(toggleAlert).toHaveBeenCalledWith(successAlert);
expect(wrapper.state().searchTerm).toBe('');
});
it('"handleSubmit" to have been called with "other than mocky"', () => {
expect(toggleAlert).not.toHaveBeenCalled();
expect(handleChange).not.toHaveBeenCalled();
wrapper.find('Input').simulate('change', { target: { value: 'Hello' } });
expect(handleChange).toHaveBeenCalledTimes(1);
expect(wrapper.state().searchTerm).toBe('Hello');
wrapper.find('Button').simulate('click');
expect(toggleAlert).toHaveBeenCalledTimes(1);
expect(toggleAlert).toHaveBeenCalledWith(errorAlert);
expect(wrapper.state().searchTerm).toBe('Hello');
});
});
そこで、まずラッパーインスタンスを更新し、次にラッパーを更新することで、実用的なソリューションを作成することができました。テストが機能するようになりました。
動作テストは次のようになります。
it('should call handleSubmit function on submit', () => {
const wrapper = shallow(<Search toggleAlert={jest.fn()} />)
wrapper.instance().handleSubmit = jest.fn()
wrapper.instance().forceUpdate()
wrapper.update()
wrapper.find('.btn').simulate('click')
expect(wrapper.instance().handleSubmit).toHaveBeenCalled()
})
このようなものを試してください
it('should call handleSubmit function on submit', () => {
const toggleAlert = jest.fn();
const wrapper = shallow(<Search toggleAlert={toggleAlert} />)
wrapper.setState({ searchText: 'mocky' });
wrapper.find('Button').at(0).simulate('click');
expect(toggleAlert).toHaveBeenLastCalledWith({
alertType: 'success',
alertMessage: 'Success!!!'
});
})
****更新
constructor(props) {
super(props) //you have to add props to access it this.props
this.state = {
searchTerm: ''
}
this.handleSubmit = this.handleSubmit.bind(this)
}
このシナリオでは、単体テストを作成する必要はありません。フレームワークが提供した正しいハンドラーを起動することを信頼できるはずです。より有用なテストは、toggleAlert
propをモックし、インスタンスメソッドhandleSubmit
をテストするテストです。これは、カスタムロジックの大部分が存在する場所であり、その結果、エラーを見つける可能性が最も高い場所です。スナップショットのテストは、レンダリング関数の出力の一部である場合は問題ありません。
このコンポーネントの実用的なテストスイートは、次のようなものになります。
describe('handleSubmit', () => {
let wrapper;
let spy;
describe('when searchTerm is "mocky"', () => {
beforeEach(() => {
spy = jest.fn();
wrapper = shallow(<SearchForm toggleAlert={spy} />);
wrapper.setState({ searchTerm: 'mocky' });
});
it('will fire spy with expected arguments', () => {
// verify that spy has not been fired prior to test
expect(spy).not.toBeCalled();
wrapper.instance().handleSubmit();
expect(spy).toBeCalled();
expect(spy).toBeCalledWith({
alertType: 'success',
alertMessage: 'Success!!!'
});
});
it('will set searchTerm to ""', () => {
expect(wrapper.state('searchTerm')).toBe('mocky');
wrapper.instance().handleSubmit();
expect(wrapper.state('searchTerm')).toBe('');
});
});
describe('when searchTerm is "something else"', () => {
beforeEach(() => {
spy = jest.fn();
wrapper = shallow(<SearchForm toggleAlert={spy} />);
wrapper.setState({ searchTerm: 'something else' });
});
it('will fire spy with expected arguments', () => {
// verify that spy has not been fired prior to test
expect(spy).not.toBeCalled();
wrapper.instance().handleSubmit();
expect(spy).toBeCalled();
expect(spy).toBeCalledWith({
alertType: 'error',
alertMessage: 'Error!!!'
});
});
});
});