2012-11-27 2 views
4

Jasmine을 배우는 과정에서이 문제가 발생했습니다. 기본 함수를 실행 한 다음 다시 호출하라는 제한 시간을 설정합니다. 간단한 작업. Expected spy setTimeout to have been called with [ Function, 10 ] but was called with [ [ Function, 10 ] ]jasmine testing coffeescript expect (setTimeout) .toHaveBeenCalledWith

는 이것을 (-> my_nifty_loop.loop(interval)) 함수가 있기 때문에 같지인가 :

class @LoopObj 
    constructor: -> 
    loop: (interval) -> 
    #do some stuff 
    setTimeout((=>@loop(interval)), interval) 

는하지만

describe "loop", -> 
    xit "does nifty things", -> 
    it "loops at a given interval", -> 
    my_nifty_loop = new LoopObj 
    interval = 10 
    spyOn(window, "setTimeout") 
    my_nifty_loop.loop(interval) 
    expect(setTimeout).toHaveBeenCalledWith((-> my_nifty_loop.loop(interval)), interval) 

나는이 오류를 얻을의 setTimeout이 적절한 인수로 호출했다 확인하기 위해 테스트 할 (=>@loop(interval)) 기능? 또는 두 번째 주위의 여분의 대괄호와 관련이 있습니까? [ [ Function, 10 ] ]? 뭔가 다른 거있어?

어디로 잘못 갔습니까?

답변

1

나는 너무 잘 커피 스크립트를 모르는,하지만 당신은

expect(setTimeout).toHaveBeenCalledWith(jasmine.any(Function), interval) 

및 사양을 다시 실행하는

expect(setTimeout).toHaveBeenCalledWith((-> my_nifty_loop.loop(interval)), interval) 

를 대체하여 디버깅 할 수 있습니다. 여분의 대괄호가 없어지면 두 개의 다른 함수 참조가 있기 때문에 문제가 있다고 생각합니다. 그들이 멀리 가지 않으면 LoopObj 정의에 약간의 이상 함, 아마도 굵은 화살표 연산자 (n00b 눈에 불필요하게 보인다)가 있습니다.

+0

jasmine.any (기능)가 작동합니다. 나는 뚱뚱한 화살이 적당한'this'와 같게하기 위해 필요하다고 확신한다. 이제 문제는 "이 시험은 철저한 시험인가?"입니다.일부 setTimeout이 호출 된 것으로 입증되었지만 테스트에서 루프가 다시 실행되는 것을 보장하지는 않습니다. 내가 기다릴 것없이 스파이해야합니까? 아니면 다른 방법? 어쩌면 상관 없어요? –

+0

Roger that : 뚱뚱한 화살. 나는 이것이 유효한 테스트 개념이라고 생각한다; LoopObj.loop에 대한 올바른 참조를 얻는 것만으로도 완벽하게 작동합니다. 익명 함수에서 my_nifty_loop.loop (interval)을 래핑하는 스펙 기대가 있습니까? 다시 n00b 눈을 통해 (-> my_nifty_loop ...) 함수 정의처럼 보입니다. –

1

bind 헬퍼 기능을 사용하십시오.

setTimeout의 인수를 비교하는 데 문제가있는 이유는 람다에 숨겨져 있기 때문입니다. 당신이 만드는 모든 람다는 다릅니다. 이 경우 람다는 실제로 함수를 적절한 값인 this에 바인딩하는 것 외에 아무 값도 추가하지 않습니다.

JavaScript의 일반적인 패턴이며 Underscore.js 라이브러리에는 bind이라는 기능이 있습니다. 정확하게 수행 할 수 있습니다.

이 패턴을 분해하여 setTimeout (이는 _.delay과 같습니다)으로 구성하면 전달 된 인수를 람다로 랩핑되지 않기 때문에 비교할 수 있습니다. 그런 다음 테스트

window.bindAndDelay = (wait, fn, obj, args...) -> 
    setTimeout((-> obj.fn(args...)), wait) 

class @LoopObj 
    constructor: -> 
    loop: (interval) -> 
    #do some stuff 
    bindAndDelay(interval, @loop, @, interval) 

는 :

describe "loop", -> 
    xit "does nifty things", -> 
    it "loops at a given interval", -> 
    my_nifty_loop = new LoopObj 
    interval = 10 
    spyOn(window, "bindAndDelay") 
    my_nifty_loop.loop(interval) 
    expect(bindAndDelay).toHaveBeenCalledWith(interval, my_nifty_loop.loop, my_nifty_loop, interval) 

나는 그것을 적용 인수의 임의의 수와 기능을 작동하도록 bindAndDelay의 첫 번째 인수로 지연 양을 넣어하기로 결정했습니다.

대체 방법은 _.bindAll이지만 모든 개체에 사용하는 것을 기억해야하며 매개 변수가있는 함수에 도움이되지 않습니다. 그래서 나는 위가 더 좋다고 생각합니다.

그래도 작동하지만 여전히 악취라고 생각합니다. 그래서 다른 사람이 더 좋은 대답을한다면, 글을 올려주세요!

관련 문제