2016-04-18 10 views
7

私はchai-as-promisedをカルマ単体テストで約束して$qと一緒に働こうとしています。

svc.test = function(foo){ 
    if (!foo){ 
     // return Promise.reject(new Error('foo is required')); 
     return $q.reject(new Error('foo is required')); 
    } else { 
     // get data via ajax here 
     return $q.resolve({}); 
    } 
    }; 


    it.only('should error on no foo', function(){ 
    var resolvedValue = MyServices.test(); 
    $rootScope.$apply(); 
    return resolvedValue.should.eventually.be.rejectedWith(TypeError, 'foo is required'); 
    }); 

単体テストがタイムアウトしました。適切に解決する約束を得るために私がここで間違っていることを私は確信していません。それは$qを使用して問題があるようです - 私がネイティブを使用する場合Promise.reject()それは正常に動作します。

私はここでチケットを提出したが、誰も応答しているように見えるん: https://github.com/domenic/chai-as-promised/issues/150

答えて

1

chai-as-promisedが約束アサーションを変更する予定の方法はtransferPromiseness methodです。デフォルトでは

、の約束の表明としてチャイによって返された約束は、入力された約束に由来する単一その後、方法 で拡張 定期チャイアサーションオブジェクトです。この動作を変更するには、たとえば など多くの約束ライブラリで が見つかったなど、より有用な砂糖法で約束を出力するには、 chaiAsPromised.transferPromisenessを上書きできます。角度1.3以降サポートについて

$q約束が$$stateプロパティでアヒル-入力できるので、ネイティブの約束は影響を受けません。

chaiAsPromised.transferPromiseness = function (assertion, promise) { 
    assertion.then = promise.then.bind(promise); 

    if (!('$$state' in promise)) 
    return; 

    inject(function ($rootScope) { 
    if (!$rootScope.$$phase) 
     $rootScope.$digest(); 
    }); 
}; 

chaiAsPromisedチェーンそれぞれがthenとの約束を主張しました。たとえ約束が解決されても、残りのチェーンは依然として手動で$rootScope.$digest()でダイジェストをトリガする必要があります。

限り仕様が全く非同期コードを含まないように、それは同期になり、何も約束を返却する必要がありません:

it('...',() => { 
    ... 
    expect(...).to.eventually...; 
    expect(...).to.eventually...; 
}); 

そしてeventuallyアサーション/期待ときtransferPromiseness wasnの各セットの後$rootScope.$digest()必須に等しいです。設定:

it('...',() => { 
    ... 
    expect(...).to.eventually...; 
    expect(...).to.eventually...; 
    $rootScope.$digest(); 
}); 
+0

は角/ $ qはそれほど一般的であり、ほとんどの企業はそれでチャイを使用するので、プラグインによって提供されているべきもののように思えます。 – chovy

+0

@chovy確かに、リストされたコードで再エクスポートするchai-as-promised用のラッパーパッケージを作成することはできます(幸いにも、それはフォークする必要はありません)。私は、Mocha/Chaiバンドルにセットアップファイルが必要であるという考えに慣れてきました。そこに余分な行がいくつかあるのは問題ではありません。 – estus

+1

@estusこのコードはどこに置かれますか? – Willa

0

テストの実行順序を変更する必要があります。期待通りの非同期タスクは、期待通りのの前にの間に起こる必要があります。

it('does not work',() => { 
    $timeout.flush(); 
    expect(myAsyncTask()).to.eventually.become('foo'); 
}) 

it('does work',() => { 
    expect(myAsyncTask()).to.eventually.become('foo'); 
    $timeout.flush();  
}) 

あなたはは、非同期タスクのキューをフラッシュする前に非同期タスクへのコールを開始する必要があります。

また、$rootScope.$digestを使用しないでください。そのにはあなたのテストで望ましくない他の副作用があるかもしれません。

$timeout.flushはあなたが探しているものです。

https://docs.angularjs.org/api/ngMock/service/ $タイムアウト


あなたの特定のテスト(複数可)の作業を取得するには、次の

it('should error on no foo', function(){ 
    MyServices.test().should.eventually.be.rejectedWith(TypeError, 'foo is required') 
    $rootScope.$apply(); 
}); 

it('should pass on foo', function(){ 
    MyServices.test('foo').should.eventually.become({}); 
    $rootScope.$apply();  
} 

TL; DR

it('async test',() => { 
    setup(); 
    expect(); 
    execute(); 
}) 

it('sync test',() => { 
    setup(); 
    execute(); 
    expect(); 
}) 

あなたが答えている質問に「ライバル」の答えをdownvoteする非倫理的であることに言及しなければならない:3210

は、投稿されたコメントを考えると?

かなり十分です。 doneコールバックを扱わなくても、Angularを使って約束したことを約束するために必要な特別な設定がないので、答えは誤解を招くと思います。 Fwiw、私は先に進み、そのdownvoteを取り消し、それについて倫理的にしようとします。

OPはコード内にタイムアウトの兆候がなく、タスクが非同期であるとは示されません。 $rootScope.$digest()はスコープダイジェストの外で呼び出されたときに仕様に副作用がありません。プロダクションで推奨されない理由は、$applyの安全対策がないためです。

$rootScope.$digestを効果$rootScope.$apply(そしてそのことについて$scope.$apply)と同じです。 source

$timeout.flushは、$timeoutベースの機能も同様にフラッシュします。 $timeoutの機能に特有のものではありません。

Plunkerそれだけで™どのように機能するかを紹介する: plunker

+0

OPにはコード内にタイムアウトの兆候がなく、タスクが非同期であるとは示されません。 '$ rootScope。$ digest()'はスコープダイジェストの外で呼び出されたときに仕様に副作用を持ちません。プロダクションで推奨されないのは、 '$ apply'が持つ安全対策がないからです。 – estus

+0

@estus私は、あなたの懸念に自分の能力で最大限に応えようとしました。また、この方法が「同期」タスクで機能するかどうかが不明な場合は、[plunker](http://plnkr.co/edit/4J3oIDSMIG7bfn9svDvq?p=preview)をチェックしてください。 –

+0

もちろん、 '$ timeout.flush()'は動作しますが、ここでは過剰な動作のように見えますが、過剰な動作は仕様上機械的に行われるべきものではありません。フラッシュされていないタイムアウトがある場合、テスターはそれらを意識して意識的にフラッシュします。さもなければ ''最終的に ''後の単なる '$ rootScope。$ digest()'で十分です。 – estus

関連する問題