我如何使用Jasmine窥探Angular承诺链

时间:2013-10-28 11:03:15

标签: angularjs jasmine

使用AngularJS,CoffeeScript和Jasmine(在WebStorm中编辑),我想对一系列承诺进行单元测试。

假设我有以下示例服务:

角色服务

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规范。

Jasmine Spec

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()

该测试的结果如下:

  • expect(@ exampleService.step1).toHaveBeenCalled() - PASS
  • expect(@ exampleService.step2).toHaveBeenCalled() - FAIL

你能告诉我如何让step2()成功地接受考验吗?

谢谢

修改

@Dashu以下提供了问题的答案。诀窍是简单地调用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()

1 个答案:

答案 0 :(得分:3)

在第二次预期之前尝试$ rootScope。$ apply()

也是关于defer.resolve()的。我不知道这是否真的解决了这个承诺,我认为它只是设置了它在结算时返回的值。

所以我会把这个转移到$ q.defer()调用之下,然后将promise传递给andReturn()

你可以做defer.resolve(true),defer.reject(false),所以如果你的承诺会在insinde callsteps中被拒绝,那么将返回true或false