2017-11-09 8 views
0

counter라는 단일 상태 값을 가진 간단한 React Parent 구성 요소가 있습니다. 상위 구성 요소 아래에 상태를 업데이트하기 위해 부모에게 다시 호출하는 onClick 처리기가있는 단추 인 단일 하위 구성 요소가 있습니다. 다음테스트 비동기 호출로 농담 문제에 반응하십시오.

import React, { Component } from 'react'; 
import axios from 'axios' 

class Parent extends Component { 
    state = {counter: 0} 

    onClickAsync =() => { 
    console.log("Async Button clicked") 
    axios.get(`https://api.github.com/users/smitp33`) 
     .then(resp => { 
      this.setState(prevState => ({ 
      counter: prevState.counter + 1 
      })) 
     } 
    ) 
    } 

    render() { 
    return (
     <div> 
     <Child onClick={this.onClickAsync} action="Click"/> 
     </div> 
    ); 
    } 
} 

class Child extends Component { 

    render() { 
    return (
     <button onClick={this.props.onClick}>{this.props.action}</button> 
    ) 
    } 
} 

export default Parent 

... : 나는 시뮬레이션하기 위해 다음과 같은 비동기 업데이트에 코드를 변경하는 경우

import React from 'react'; 
import {mount, shallow} from 'enzyme'; 
import Parent from '../Problem'; 

it('handles Click event',() => { 

    const wrapper = mount(<Parent />) 
    expect(wrapper.state().counter).toEqual(0) 
    console.log(wrapper.debug()) 
    const button = wrapper.find('button').at(0); 
    button.simulate('click'); 
    expect(wrapper.state().counter).toEqual(1) 
    console.log(wrapper.state().counter) 

}); 

:

import React, { Component } from 'react'; 
import axios from 'axios' 

class Parent extends Component { 
    state = {counter: 0} 

    onClick =() => { 
    console.log("Button clicked") 
    this.setState(prevState => ({ 
     counter: prevState.counter + 1 
    })) 
    } 

    render() { 
    return (
     <div> 
     <Child onClick={this.onClick} action="Click"/> 
     </div> 
    ); 
    } 
} 

class Child extends Component { 

    render() { 
    return (
     <button onClick={this.props.onClick}>{this.props.action}</button> 
    ) 
    } 
} 

export default Parent 

이는 다음의 시험으로 농담을 사용하여 고급 테스트 카운터가 업데이트 된 것으로 보이지 않으므로 동일한 테스트가 실패합니다.

handles Click event 

    expect(received).toEqual(expected) 

    Expected value to equal: 
     1 
    Received: 
     0 

     at Object.<anonymous>.it (src/__tests__/Problem.test.js:14:35) 
     at Promise.resolve.then.el (node_modules/p-map/index.js:46:16) 
     at process._tickCallback (internal/process/next_tick.js:109:7) 

나는 상태가 참으로 변경되었음을 증명하는 setState를 함수에 콜백을 추가하고 확실히있다, 그래서 문제가 단순히 비동기 구성 요소 호출이 완료되기 전에 완료 농담 테스트 주위 믿습니다.

나는 여러 가지 기사와 유태인 문서를 읽었으며 여기에 모든 것을 시험해보고 시험을 통과했지만 아직 성공하지 못했다. 그래서 나는 누군가가 어떤 것을 제공 할 수 있는지 여기에 게시 할 것이라고 생각했다. 이것이 정확히 어떻게 접근되어야하는지 명확한 조언. 다음과 같이 정확한 의존성에

내역은 다음과 같습니다 :

"dependencies": { 
    "axios": "^0.17.0", 
    "enzyme": "^3.1.0", 
    "enzyme-adapter-react-16": "^1.0.2", 
    "jest-enzyme": "^4.0.1", 
    "prop-types": "^15.6.0", 
    "react": "^16.0.0", 
    "react-circular-progressbar": "^0.5.0", 
    "react-dom": "^16.0.0", 
    "react-percentage-circle": "^1.1.3", 
    "react-scripts": "1.0.15" 
    } 

모든 바닐라에서 이루어집니다 '생성 - 반응 - 응용 프로그램'설정을가 setupTests.js에 정의 된 다음과 :

import Enzyme from "enzyme"; 
import 'jest-enzyme'; 
import Adapter from "enzyme-adapter-react-16"; 

Enzyme.configure({ adapter: new Adapter() }); 

global.requestAnimationFrame = function(callback) { 
    setTimeout(callback, 0); 
}; 

답변

0

this.setState은 비동기 방식으로 작동합니다. 따라서 상태를 설정한다고해서 즉시 업데이트된다는 의미는 아닙니다. 당신의 테스트에서 말했다와

onClickAsync =() => { 
    console.log("Async Button clicked") 
    axios.get(`https://api.github.com/users/smitp33`) 
    .then(resp => { 
     this.setState({ 
     counter: this.state.counter + 1; 
     },() => { 
     console.log(this.state.counter); 
     }) 
    } 
    ) 
} 

을, 어떤 주장을하기 전에 완료 비동기 작업 대기 : 당신의 async 함수에서, 오히려 이것을 시도. 즉, 실제로 어설 션을 수행 할 곳인 .then() 메서드를 활용하십시오. 나는 위에 제공되는 사항으로

+0

감사 - 나는 setState를 호출은 따라서 당신이 언급 똑같이 콜백 테스트 한 바로 아니라는 것을 알지 못했다. 흥미롭게도 코드를 정상적으로 실행하면 Jest 내부에서 실행될 때 console.log 출력이 표시되지만 그렇지 않은 경우도 있습니다.위의 힌트를 사용하여 나는 여기서 그들이 중요한 것은 Jest가 행복하게 처리 할 약속에 의존한다는 것임을 깨달았습니다 ... 실제 Promise를 반환하는 함수를 변경해야합니다. – smitp33

+0

예. – brandNew

0

다음과 같이이 작업을 얻을 수 있었다 :

을 대신 내가 분리의 기능을 테스트하기로 결정했습니다 시뮬레이션의 일환으로 비동기 클릭을 테스트하는.

실제로 뭔가를 반환하도록 click 이벤트를 수정함으로써 ...이 경우 Promise는 비동기를 올바르게 사용할 수 있었으며 테스트에서 기다리고있었습니다.

수정 된 코드 :

onClickAsync =() => { 
    console.log("Async Button clicked") 
    return (
     axios.get(`https://api.github.com/users/smitp33`) 
      .then(resp => { 
       this.setState(prevState => ({ 
       counter: prevState.counter + 1 
       })) 
      } 
     ) 
    ) 
    } 

수정 된 테스트 : fshock

test('calls Async Click function', async() => { 
    const wrapper = mount(<Parent />) 
    console.log(wrapper.state().counter) 
    await wrapper.instance().onClickAsync() 
    console.log(wrapper.state().counter) 
    expect(wrapper.state().counter).toEqual(1) 
});