2017-01-13 4 views
9

나는 다음 돌아 오는 행동 작성자가 :어떻게 단위 썽크 작업과 테스트 mapDispatchToProps을에

export const keyDown = key => (dispatch, getState) => { 
    const { modifier } = getState().data; 
    dispatch({ type: KEYDOWN, key }); 
    return handle(modifier, key); // Returns true or false 
}; 

그리고 다음 연결된 기기 : 나는 dispatch을 보장하기 위해 테스트를 작성하는 것을 시도하고있다

export const mapDispatchToProps = dispatch => ({ 
    onKeyDown: e => { 
     if(e.target.tagName === "INPUT") return; 
     const handledKey = dispatch(keyDown(e.keyCode)); 
     if(handledKey) { 
      e.preventDefault(); 
     } 
    } 
}); 

tagName"INPUT"이 아닌 경우 keyDown 작업으로 호출됩니다. 이것은 내 테스트입니다 :

import { spy } from "sinon"; 
import keycode from "keycodes"; 
import { mapDispatchToProps } from "./connected-component"; 
import { keyDown } from "./actions"; 

// Creates a simple Event stub... 
const createEvent = (tag, keyCode) => ({ 
    target: { 
     tagName: tag.toUpperCase() 
    }, 
    preventDefault: spy(), 
    keyCode 
}); 

it("Dispatches a keyDown event with the specified keyCode if the selected element is not an <input>",() => { 
    const dispatch = spy(); 
    const keyCode = keycode("u"); 
    mapDispatchToProps(dispatch).onKeyDown(createEvent("div", keyCode)); 
    // This fails... 
    expect(dispatch).to.have.been.calledWith(keyDown(keycode)); 
}); 

아마도 이것은 화살표 기능을 사용하는 것과 관련이 있습니까? 내가 기대하는 함수 서명으로 파견을 호출 할 수있는 방법이 있습니까?

+0

그래서 당신은 문자열 평등과 return 문 작동을 테스트 또는 개발자가 실수로 제거하지 않았다입니까? 하나님, 나는 대부분의 단위 테스트를 싫어한다. ( –

+0

주로'dispatch'가 실제로 호출된다. 나는 액션 생성자를 디스패치하지 않고 호출한다 .keyDown 액션도 중요하므로'expect (dispatch). to.have.been.called'는 충분하지 않을 것입니다. – CodingIntrigue

답변

3

가장 간단한 해결책은 다른 대답 (+1)에서 제안한대로 keyDown()을 메모하는 것일 수 있습니다. 여기 keyDown() 이후


actions에서 수입되는 모든 기지를 커버하려고 다른 방법은 ...입니다 우리 수 stubkeyCode으로 호출되는 때마다 dummy 값을 반환하는 기능 :

import * as actions; 
keyDown = stub(actions, "keyDown"); 
keyDown.withArgs(keyCode).returns(dummy); 

그런 다음 unit tests은 이전에 설정 한 dummy과 함께 dispatch이 호출되었는지 확인합니다. dummy은 우리의 스텁 된 keyDown()에 의해서만 반환 될 수 있으므로이 검사에서도 keyDown()이 호출되었는지 확인합니다.

mapDispatchToProps(dispatch).onKeyDown(createEvent("div", keyCode)); 
expect(dispatch).to.have.been.calledWith(dummy); 
expect(keyDown).to.have.been.calledWithExactly(keyCode); 

우리가 키 이벤트 대상이 <input> 때 전달 하지 것을 확인하는 단위 테스트를 추가해야합니다, 철저합니다.

mapDispatchToProps(dispatch).onKeyDown(createEvent("input", keyCode)); 
expect(dispatch).to.not.have.been.called; 
expect(keyDown).to.not.have.been.called; 

우리는 주어진 dispatch 콜백이 올바른 키 이벤트 및 키 코드로 호출되는 것을 확인하여도 testkeyDown() 자체 분리의를 수행해야합니다

expect(dispatch).to.have.been.calledWith({type: actions.KEYDOWN, key: keyCode}); 

링크

+0

답장을 보내 주셔서 감사합니다. ES6 수입품이 그런 식으로 스터빙 될 수는 없다는 것을 깨달았지만, 의미가 있습니다. 동일한 점, 나는 대답에 넣은 노력의 수준에 대해 현상금을 수여했다. – CodingIntrigue

+0

@ 코딩 방해 문제 없음 :) – tony19

2

keyDown(keycode)은 매번 새로운 함수를 만들고 모든 함수 인스턴스가 다르므로 테스트 사례가 예상대로 실패합니다.

은 암기 keyDown 의해 생성 기능에 의해 수정 될 수있다 : 동일한 keycode 창으로

암기
let cacheKeyDown = {}; 
export const keyDown = key => cacheKeyDown[key] || cacheKeyDown[key] = (dispatch, getState) => { 
    const { modifier } = getState().data; 
    dispatch({ type: KEYDOWN, key }); 
    return handle(modifier, key); 
}; 

, keyDown 호출 동일한 기능.

1

@DarkKnight가 +1 했으므로 keyDown은 모든 호출에 대해 새 함수를 반환하므로 keyDown(keyCode)! = keyDown(keyCode)이므로 테스트가 실패합니다. 당신이 keyDown의 실제 구현을 변경하지 않으려면

, 당신은 당신의 테스트에서 조롱 수 있습니다