4

AngularJS、CoffeeScript、および Jasmine (WebStorm で編集) を使用して、promise のチェーンを単体テストしたいと思います。

次のサンプル サービスがあるとします。

Angular サービス

class ExampleService
    stepData: []
    constructor: (@$http) ->

    attachScopeMethod: (@scope) ->
        @scope.callSteps = => @step1().then -> @step2()

    step1: ->
        @$http.get('app/step/1').then (results) =>
            @stepData[0] = results.data
            results

    step2: ->
        @$http.get('app/step/2').then (results) =>
            @stepData[2] = results.data
            results

このサービスを使用すると、メソッドcallSteps()をスコープにアタッチできます。このメソッドが呼び出されると、サードパーティ API への一連の非同期 $http 呼び出しが実行されます。

各ステップが少なくとも呼び出されることをテストするために、次の Jasmine 仕様を作成しました。

ジャスミンスペック

ddescribe 'ExampleService', ->

    beforeEach ->
        module 'myApp'

    beforeEach inject ($rootScope, $injector) ->
        @scope = $rootScope.$new()
        @exampleService = $injector.get 'exampleService'
        @q = $injector.get '$q'

    describe 'process example steps', ->
        beforeEach  -> 
            @exampleService.attachScopeMethod(@scope)

        it "should attach the scope method", ->
            expect(@scope.callSteps).toBeDefined()

        describe 'when called should invoke the promise chain', ->

        it "should call step1 and step2", ->
            defer = @q.defer()
            @exampleService.step1 = jasmine.createSpy('step1').andReturn(defer.promise)

            @exampleService.step2 = jasmine.createSpy('step2')

            @scope.callSteps()
            defer.resolve()

            expect(@exampleService.step1).toHaveBeenCalled()
            expect(@exampleService.step2).toHaveBeenCalled()

このテストの結果は次のとおりです。

  • 期待する (@exampleService.step1).toHaveBeenCalled() - PASS
  • 期待する (@exampleService.step2).toHaveBeenCalled() -失敗

step2()テスト中に正常に実行する方法を教えてください。

ありがとうございました

編集

以下の@Dashuは、問題に対する回答を親切に提供してくれました。秘訣は、Promise チェーンの解決を呼び出すscope.$applyscope.$digestトリガーするだけです。

これが実際のテスト フラグメントです。

describe 'when called should invoke the promise chain', ->
    it "should call step1 and step2", ->
        defer = @q.defer()
        defer.resolve()

        @exampleService.step1 = jasmine.createSpy('step1').andReturn(defer.promise)
        @exampleService.step2 = jasmine.createSpy('step2')

        @scope.callSteps()
        @scope.$apply()

        expect(@exampleService.step1).toHaveBeenCalled()
        expect(@exampleService.step2).toHaveBeenCalled()
4

1 に答える 1

3

2 番目の予想の前に $rootScope.$apply() を試してください

defer.resolve() についても。これが実際に約束を解決するかどうかはわかりません。解決時に返される値を設定するだけだと思います。

そのため、プロミスを andReturn() に渡す前に、$q.defer() 呼び出しのすぐ下まで移動します。

defer.resolve(true)、defer.reject(false) を実行できるため、コールステップ内で約束が拒否される場合、true または false が返されます。

于 2013-10-28T15:09:35.210 に答える