2

남자,이 파이어베이스 유닛 테스트가 실제로 내 엉덩이를 차고 있습니다.유닛 테스트 파이어베이스 용 클라우드 기능 : sinon.js로 '트랜잭션'을 테스트/모의하는 "올바른 방법"은 무엇입니까

내가 the documentation를 통과하고 그들이 제공하는 예제를 통해 읽고, 내 기본적인 중포 기지 기능 단위 테스트의 일부를 입수했습니다,하지만 난이 transactionUpdated 있는지 확인하는 방법을 잘 모르겠어요 문제가 실행 계속했습니다 함수 .transaction에 전달 된 함수가 current 개체를 올바르게 업데이트하고 있습니다.

내 투쟁은 아마도 child-count sample code과 그 단위 테스트를 작성하는 데 실패한 시도로 가장 잘 설명됩니다.

// count.js 
exports.countlikechange = functions.database.ref('/posts/{postid}/likes/{likeid}').onWrite(event => { 
     const collectionRef = event.data.ref.parent; 
     const countRef = collectionRef.parent.child('likes_count'); 

     // ANNOTATION: I want to verify the `current` value is incremented 
     return countRef.transaction(current => { 
     if (event.data.exists() && !event.data.previous.exists()) { 
      return (current || 0) + 1; 
     } 
     else if (!event.data.exists() && event.data.previous.exists()) { 
      return (current || 0) - 1; 
     } 
     }).then(() => { 
     console.log('Counter updated.'); 
     }); 
    }); 

단위 테스트 코드 :

const chai = require('chai'); 
const chaiAsPromised = require("chai-as-promised"); 
chai.use(chaiAsPromised); 
const assert = chai.assert; 
const sinon = require('sinon'); 

describe('Cloud Functions',() => { 
    let myFunctions, functions; 

    before(() => { 
    functions = require('firebase-functions'); 
    myFunctions = require('../count.js'); 
    }); 

    describe('countlikechange',() => { 
    it('should increase /posts/{postid}/likes/likes_count',() => { 
     const event = { 
     // DeltaSnapshot(app: firebase.app.App, adminApp: firebase.app.App, data: any, delta: any, path?: string); 
     data: new functions.database.DeltaSnapshot(null, null, null, true) 
     } 

     const startingValue = 11 
     const expectedValue = 12 

     // Below code is misunderstood piece. How do I pass along `startingValue` to the callback param of transaction 
     // in the `countlikechange` function, and spy on the return value to assert that it is equal to `expectedValue`? 
     // `yield` is almost definitely not the right thing to do, but I'm not quite sure where to go. 
     // How can I go about "spying" on the result of a stub, 
     // since the stub replaces the original function? 
     // I suspect that `sinon.spy()` has something to do with the answer, but when I try to pass along `sinon.spy()` as the yields arg, i get errors and the `spy.firstCall` is always null. 
     const transactionStub = sinon.stub().yields(startingValue).returns(Promise.resolve(true)) 

     const childStub = sinon.stub().withArgs('likes_count').returns({ 
     transaction: transactionStub 
     }) 
     const refStub = sinon.stub().returns({ parent: { child: childStub }}) 

     Object.defineProperty(event.data, 'ref', { get: refStub }) 

     assert.eventually.equals(myFunctions.countlikechange(event), true) 
    }) 
    }) 
}) 

나는 위의 소스 코드를 주석

의 내가 (링크 위에 그에서 직접 촬영) 다음을 수행 단위 테스트하려는 제 기능을한다고 가정 해 봅시다 내 질문과 함께,하지만 여기에 그것을 반복 할 것입니다.

내가 거래 스텁에 전달 된 transactionUpdate callback이, 내 startingValue을 가지고 expectedValue에 돌연변이 다음 날 그 변화를 관찰하고 무슨 일이 있었 주장 할 수 있는지 확인하는 방법에 대해 설명합니다.

이것은 명백한 해결 방법으로는 아마도 매우 간단한 문제 일 수 있습니다.하지만 모든 것이 스텁되어야하는 JS 코드를 테스트하는 데있어 매우 익숙합니다. 그래서 약간의 학습 곡선이 있습니다 ... 어떤 도움을 주시면 감사하겠습니다.

답변

4

Firebase 생태계의 단위 테스트가 우리가 원하는 것처럼 쉽지 않음에 동의합니다. 팀은 그것을 알고 있으며, 우리는 일을 더 잘하기 위해 노력하고 있습니다! 다행히도, 거기에 앞으로 좋은 방법 몇 가지 있습니다!

방금 ​​게시 한 this Cloud Functions demo을 살펴 보시기 바랍니다. 이 예제에서 우리는 TypeScript를 사용하지만 이것은 모두 JavaScript에서도 작동합니다. 우리가 세 개의 파일로 로직을 분리 한 알거야 src 디렉토리에서

는 : index.tssaythat.ts는 우리의 주요 비즈니스 로직을 가지고, 엔트리 논리를 가지고 있으며, db.ts는 중포 기지 실시간 데이터베이스 주위에 얇은 추상화 계층이다 . 단위 테스트는 saythat.ts입니다. 우리는 의도적으로 index.tsdb.ts을 정말 간단하게 유지했습니다.

spec 디렉토리에는 단위 테스트가 있습니다. index.spec.ts을 살펴보십시오. 찾는 속임수 : usemock-require 전체 src/db.ts 파일을 조롱하고 spec/fake-db.ts으로 바꿉니다. 실제 데이터베이스에 쓰는 대신 우리가 수행 한 작업을 메모리에 저장합니다. 단원 테스트에서 올바르게 작동하는지 확인할 수 있습니다. 구체적인 예로는 score 필드 인 updated in a transaction입니다. mocking 데이터베이스를 사용하면 올바르게 수행되었는지 확인하기위한 단위 테스트가 a single line of code입니다.

시험에 도움이 되었기를 바랍니다.

+0

원더풀! 리소스와 응답에 감사드립니다.테스트 외에도 클라우드 기능 제품에 정말 감동했습니다. 정말 강력한 기능입니다. 테스트 부서에서 부족한 문서도 일반적으로 좋습니다. 당신과 당신 팀에게 큰 도움이됩니다. – tim

+0

감사합니다! 더 이상 문제가 발생하면 알려주십시오. 우리는 모든 것을 멋지게 만들고 싶어합니다. :) –

+0

@ Robert-JanHuijsman 나는 또한 이것이 저와 다른 많은 사람들을위한 백엔드의 미래가 될 것이라고 생각하면서 나는 지난 3 일 동안 그것에 대해 헌신했습니다. 내가 원했던 한 가지는 로드맵이었습니다. 그래서 우리는 당신이 무엇을하고 있는지 알 수 있습니다. – Ced