2016-12-22 15 views
1

以下は、テストしようとしているコードの単純化バージョンです。定期的に空になる単純なキューです。キュー内の各番号について、それを(この例では架空の)APIアドレスに送信するためのHTTP POSTが行われます。 POSTが成功すると、その番号はキューからシフトされ、次の番号が考慮されます。プロミスリターン関数を呼び出す再帰メソッドのユニットテスト

class Queue { 
    queue: Array<number>; 
    processingQueue: boolean; 

    constructor(public $http: angular.IHttpService) { 
     this.queue = new Array<number>(); 
     this.processingQueue = false; 
    } 

    startQueueProcessor() { 
     this.processingQueue = false; 

     setInterval(() => { 
      if (!this.processingQueue) 
       this.processQueue(); 
     }, 1000); 
    } 

    postNumber(number: number): angular.IHttpPromise<{}> { 
     return this.$http.post('http://mydummyurl.com/givemeanumber', number); 
    } 

    processQueue(): void { 
     this.processingQueue = true; // we are currently processing a queue, so make sure setInterval does not trigger another processing run 

     if (this.queue.length !== 0) { // are there any numbers to deal with? 
      const item = this.queue[0]; // get the first number in the queue 

      this.postNumber(item) // POST it (returns a promise) 
       .then(
       () => { // if successful... 
        this.queue.shift(); // we've dealt with this item, so remove it from the queue 
        this.processQueue(); // check the queue again (recurses until all items have been dealt with) 
       }, 
       () => { // if unsuccessful... 
        this.processingQueue = false; // something went wrong, so stop 
       } 
       ); 
     } else { 
      this.processingQueue = false; // queue is empty, stop processing 
     } 
    } 

    enqueue(number: number): void { // add a number to the queue 
     this.queue.push(number); 
    } 
} 

私が作成したいテストはキューに追加された3つのアイテムを持った後、processQueue()への単一の呼び出しがそれを空になる、ということをチェックします。 (ジャスミンにアップ嘲笑)このような

何か:

describe('queueing',() => { 
    var queueService; 

    beforeEach(inject((_$httpBackend_, $injector) => { 
     httpBackend = _$httpBackend_; 
     httpBackend.whenPOST().respond(200); 

     queueService = $injector.get('queue'); 
    })); 

    it('should clear queue completely when processQueue() is called once',() => { 

     queueService.enqueue(1); 
     queueService.enqueue(2); 
     queueService.enqueue(3); 

     expect(queueService.queue.length).toBe(3); 

     queueService.processQueue(); 

     // somehow wait for processQueue() to complete 

     expect(queueService.queue.length).toBe(0); 
    }); 
}); 

私の問題は、第二expect()は常にメッセージExpected 3 to be 0で失敗していることです。私はこれが、postNumber()が待たずに返される約束によるものだと仮定しているので、第2のexpect()が呼び出されるまでにキューは空ではありません。

processQueue()が完了するのを待ってから、キューが空になったことをアサートします。

答えて

0

プロミスを返すには、processQueueを変更する必要があります。

テストで
async processQueue(): Promise<void> 
{ 
    this.processingQueue = true; // we are currently processing a queue, so make sure setInterval does not trigger another processing run 

    if (this.queue.length !== 0) 
    { // are there any numbers to deal with? 
     const item = this.queue[0]; // get the first number in the queue 

     try 
     { 
      await this.postNumber(item); // POST it (returns a promise) 
      // if successful... 
      this.queue.shift(); // we've dealt with this item, so remove it from the queue 
      this.processQueue(); // check the queue again (recurses until all items have been dealt with) 
     } 
     catch 
     { 
       this.processingQueue = false; // something went wrong, so stop 
     } 
    } 
    else 
    { 
     this.processingQueue = false; // queue is empty, stop processing 
    } 
} 

そして:そうするための最も簡単な方法は、asyncキーワードでメソッドをマークし、上、後awaitを使用している

it('should clear queue completely when processQueue() is called once', async (done) => { 

    queueService.enqueue(1); 
    queueService.enqueue(2); 
    queueService.enqueue(3); 

    expect(queueService.queue.length).toBe(3); 

    await queueService.processQueue(); 

    // somehow wait for processQueue() to complete 

    expect(queueService.queue.length).toBe(0); 

    done(); 
});  

は、この情報がお役に立てば幸いです。

+0

@Amidのご提案ありがとうございます。 'エラー:タイムアウト - 非同期コールバックがjasmine.DEFAULT_TIMEOUT_INTERVALで指定されたタイムアウト時間内に呼び出されていませんでした。 ' 最初のアサーションは正しく終了しましたが、' await'セクション何かを返すようではないとそれはタイムアウトします。 – Outrigger

+0

私はそれには2つの理由があります。 http.postがホストに到達せず、操作がタイムアウトしました。または、(そしてこれはおそらく)angular.IHttpPromiseはtypescriptによって使用される一般的なA + promiseと互換性がありません。変換の例については、次の2つのリンクを参照してください。https://www.codeproject.com/articles/1019920/building-angularjs-application-with-typescript-and http://stackoverflow.com/questions/24611078/how-変換 - 角度 - 約束 - 遅延オブジェクト – Amid

関連する問題