Sinon: `getStackFrames()[0]` 문제

에 λ§Œλ“  2016λ…„ 06μ›” 12일  Β·  3μ½”λ©˜νŠΈ  Β·  좜처: sinonjs/sinon

κ·€ν•˜μ—κ²Œ λ¬Έμ œκ°€ μžˆλ‹€λŠ” 것을 μ΄ν•΄ν•˜κ³  κΈ‰ν•˜κ²Œ μ²˜λ¦¬ν•˜κ³  μžˆμŠ΅λ‹ˆλ‹€. κ·ΈλŸ¬λ‚˜ κ·€ν•˜μ˜ 문제λ₯Ό 보닀 μ‹ μ†ν•˜κ²Œ μ΄ν•΄ν•˜κ³ , μž‘μ—…ν•˜κ³ , ν•΄κ²°ν•  수 μžˆλ„λ‘ λͺ‡ 가지 정보λ₯Ό μ œκ³΅ν•΄ μ£Όμ‹œκΈ° λ°”λžλ‹ˆλ‹€.

  • μ‹œλ…Ό 버전 : 1.17.4
  • ν™˜κ²½ : νŒŒμ΄μ–΄ν­μŠ€
  • μ˜ˆμ‹œ URL:
  • μ‚¬μš© 쀑인 λ‹€λ₯Έ 라이브러리: mocha, chai

무슨 일이 일어날 것이라고 μ˜ˆμƒν–ˆμŠ΅λ‹ˆκΉŒ?

λ‚΄λΆ€ Sinon 였λ₯˜κ°€ μ•„λ‹ˆλΌ λ‚΄ μžμ‹ μ˜ 였λ₯˜κ°€ 보고될 κ²ƒμœΌλ‘œ μ˜ˆμƒν–ˆμŠ΅λ‹ˆλ‹€.

μ‹€μ œλ‘œ μΌμ–΄λ‚˜λŠ” 일

λ‚΄λΆ€ Sinon 였λ₯˜κ°€ ν‘œμ‹œλ©λ‹ˆλ‹€.

λ²ˆμ‹ 방법

잘λͺ»λœ 행동을 μž¬ν˜„ν•˜λŠ” 방법을 _μ½”λ“œλ‘œ_ μ„€λͺ…ν•˜μ‹­μ‹œμ˜€.
λ˜λŠ” JSbin λ˜λŠ” 이와 μœ μ‚¬ν•œ μ½”λ“œμ— λŒ€ν•œ 링크

예λ₯Ό 보렀면 이것을 μ°Έμ‘°ν•˜μ‹­μ‹œμ˜€.

sinon/lib/sinon/call.js μ—μ„œ 이 μ½”λ“œλŠ” this.getStackFrames(...)[0] is undefined 였λ₯˜λ₯Ό μ œκ³΅ν•©λ‹ˆλ‹€.

      if (this.stack) {
            callStr += this.getStackFrames()[0].replace(/^\s*(?:at\s+|@)?/, " at ");
      }

λ‹€μŒμ—μ„œ:

    getStackFrames: function () {
        // Omit the error message and the two top stack frames in sinon itself:
        return this.stack && this.stack.split("\n").slice(3);
    },

... slice κ°€ 빈 배열을 λ°˜ν™˜ν•˜λŠ” 것 κ°™μŠ΅λ‹ˆλ‹€.

λ‚˜λŠ” 이것이 νŠΉμ • μ½”λ“œ μƒ˜ν”Œ 없이 κ³„μ†ν•˜κΈ°μ— μΆ©λΆ„ν•  수 있기λ₯Ό λ°”λžλ‹ˆλ‹€. 감사 ν•΄μš”!

κ°€μž₯ μœ μš©ν•œ λŒ“κΈ€

이것은 Nodeμ—μ„œλ„ μž‘λ™ν•˜λŠ” μ•½κ°„ 더 λ‚˜μ€ 버전일 수 μžˆμŠ΅λ‹ˆλ‹€.

let sinon = require('sinon');

function test() {

  let stub1 = sinon.stub().returns( Promise.resolve({}) );
  let stub2 = sinon.stub();

  function run() {
    return stub1().then( stub2 );
  }

  run()
  .then( () => sinon.assert.calledTwice( stub2 ) )
  .catch( console.log );

}

setTimeout( test, 0 );

λͺ¨λ“  3 λŒ“κΈ€

μ΄κ²ƒλ§ŒμœΌλ‘œλŠ” μΆ©λΆ„ν•˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€. Sinon의 APIλ₯Ό μ‚¬μš©ν•˜λŠ” μ½”λ“œλŠ” μ „ν˜€ 보이지 μ•ŠμŠ΅λ‹ˆλ‹€. Sinon의 λ‚΄λΆ€λŠ” μ–ΈκΈ‰ν–ˆμ§€λ§Œ μ™ΈλΆ€λŠ” μ–΄λ–»μŠ΅λ‹ˆκΉŒ? 당신은 무엇을 λ‹¬μ„±ν•˜κΈ° μœ„ν•΄ λ…Έλ ₯ν•˜κ³  μžˆμŠ΅λ‹ˆκΉŒ? λ‹¬μ„±ν•˜λ €λŠ” λ‚΄μš©, 방법 및 μž‘λ™ν•˜μ§€ μ•ŠλŠ” λ‚΄μš©μ„ λͺ…ν™•νžˆ ν•˜λŠ” 정보λ₯Ό 더 μΆ”κ°€ν•˜λ©΄ 이λ₯Ό λ‹€μ‹œ μ—΄ 수 μžˆμŠ΅λ‹ˆλ‹€.

Mac용 Chrome 55.0.2883.95μ—μ„œ Sinon 1.17.6(μ΅œμ‹  버전은 http://sinonjs.org/μ—μ„œ μ‚¬μš© κ°€λŠ₯)μ—μ„œ 이λ₯Ό μž¬ν˜„ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

λ‹€μŒμ€ ν…ŒμŠ€νŠΈ μΌ€μ΄μŠ€κ°€ μΆ•μ†Œλœ JSBinμž…λ‹ˆλ‹€. http://jsbin.com/mufotihiwo/edit?js ,console,output

본질적으둜 μŠ€ν…μ΄ Promise#then() 포인트 ν”„λ¦¬λ‘œ 전달될 λ•Œ Sinon은 3쀄보닀 κΈ΄ μŠ€νƒ 좔적이 μžˆμ–΄μ•Ό ν•œλ‹€κ³  μƒκ°ν•˜μ§€λ§Œ 그렇지 μ•ŠμŠ΅λ‹ˆλ‹€.

아직 μ •ν™•ν•œ 원인을 μ•Œμ•„λ‚Ό κΈ°νšŒκ°€ μ—†μ—ˆμŠ΅λ‹ˆλ‹€.

콜백이 VM에 μ˜ν•΄ 직접 호좜되기 λ•Œλ¬Έμ΄λΌκ³  μƒκ°ν•©λ‹ˆλ‹€. 즉, μŠ€νƒμ— 아무것도 μ—†μŠ΅λ‹ˆλ‹€. λ”°λΌμ„œ Sinon이 처음 μ„Έ 쀄( spy.invoke() μ—μ„œ μ‹œμž‘)을 자λ₯΄λ©΄ 아무 것도 남지 μ•ŠμŠ΅λ‹ˆλ‹€. 그러면 getStackFrames()[0] κ°€ undefined 이기 λ•Œλ¬Έμ— getStackFrames()[0] call.toString String#replace() in call.toString κ°€ μ‹€νŒ¨ν•©λ‹ˆλ‹€.

λ‚˜λŠ” μ™„ν™” μ „λž΅μ΄ λ‹€μŒκ³Ό 같은 toString() λ°©μ–΄ 체크λ₯Ό ν•˜λŠ” 것이라고 μƒκ°ν•©λ‹ˆλ‹€.

callStr += ( this.getStackFrames()[0] || 'unknown function' ).replace(/^\s*(?:at\s+|@)?/, " at ");

이것은 Nodeμ—μ„œλ„ μž‘λ™ν•˜λŠ” μ•½κ°„ 더 λ‚˜μ€ 버전일 수 μžˆμŠ΅λ‹ˆλ‹€.

let sinon = require('sinon');

function test() {

  let stub1 = sinon.stub().returns( Promise.resolve({}) );
  let stub2 = sinon.stub();

  function run() {
    return stub1().then( stub2 );
  }

  run()
  .then( () => sinon.assert.calledTwice( stub2 ) )
  .catch( console.log );

}

setTimeout( test, 0 );
이 νŽ˜μ΄μ§€κ°€ 도움이 λ˜μ—ˆλ‚˜μš”?
0 / 5 - 0 λ“±κΈ‰