【问题标题】:How to test a Controller which relies on an ngResource Service如何测试依赖于 ngResource 服务的控制器
【发布时间】:2012-10-27 01:24:47
【问题描述】:

我有一个控制器,它依赖于通过 ngResource 构建的服务。我在测试这个时遇到了麻烦(尽管两者在实际应用程序中看起来都像一个魅力)。以下是(经过消毒的)控制器

MyApp.Controller.MyCarsController = (scope, http, typeService) ->
  if scope.context==undefined
    scope.ferrari_or_porshe =""
    scope.id = ""
  else if scope.context=="ferrari"
    scope.country_or_pi ="Ferrari"
  else if scope.context=="porshe"
    scope.country_or_pi ="Porshe"

  typeService.index
    ferrari_or_porshe: scope.ferrari_or_porshe
    id: scope.id
  , (response) ->
    scope.type = response
    scope.loading = false

MyApp.Controller.MyCarsController.$inject = ['$scope', '$http', 'Type']

这就是服务:

MyApp.MyModule.factory 'Type', ['$resource', ($resource) ->
  TypeResource = $resource("/api/types/:ferrari_or_porshe/:id", {},
    index:
      method: "GET"
      isArray: true
  )
  return TypeResource
]

最后是一些测试代码:

describe 'MyApp.Controller.MyCarsController', ->
  beforeEach module('MyModule')
  beforeEach inject ($rootScope, $http, $controller, Type) ->
    @scope = $rootScope.$new()
    @typeService = Type
    @scope.context = undefined
    $controller 'MyApp.Controller.MyCarsController', $scope: @scope

  describe '#home-page', ->

    it 'contains a list of types', ->
      expect(@scope.types.length).toBeGreaterThan 0

    it "sets instance variables correctly", ->
      expect(@scope.ferrari_or_porshe).toBe ""
      expect(@scope.id).toBe ""

失败的原因是:

  No more request expected in helpers/angular-mocks.js on line 889
  TypeError: 'undefined' is not an object (evaluating 'this.scope.types.length') in controllers/my_cars_controller_spec.js

通过明智地应用console.logs,我发现问题在于响应的最终回调永远不会到达。 TypeResource 作为 [Function] 返回。

我的问题是:

如何驱动 Jasmine 测试以正确进入服务并获取响应?有没有办法为服务创建直接单元测试?

感谢所有帮助

【问题讨论】:

  • 天啊,你不能像普通人一样用javascript写吗?
  • 是的,我已经学会了不喜欢咖啡脚本......对不起:(

标签: coffeescript angularjs jasmine


【解决方案1】:

解决方案如下:对于Service,使用作为ngMock的一部分捆绑的$httpBackend:

http://code.google.com/p/google-drive-sdk-samples/source/browse/ruby/app/lib/angular-1.0.0/angular-mocks-1.0.0.js?r=c43c943e32be395b7abca8150deb301d3cbc0dbe

使用它来模拟 Rest 响应。因为就我而言,我只关心验证 GET 请求是否发出:

 describe 'Type', ->
   describe '#index', ->
     beforeEach module('MyModule')
     beforeEach inject(($httpBackend) ->
       $httpBackend.whenGET('/api/types/ferrari/1').respond([])
     )

     it 'for a ferrari scope', inject((Type) ->
       ferrari_or_porsche = 'ferrari'
       id = '1'
       expect( Type.index('ferrari_or_porsche': ferrari_or_porsche, 'id': id) ).toEqual([ ])
     )

然后对于控制器,使用 jasmine 间谍模拟服务并使用 jasmine.any(Function) 警告回调。

 describe 'MyApp.Controller.MyCarsController', ->
   beforeEach module('myModule')
   beforeEach inject ($rootScope, $http, $controller, Type) ->
     @scope = $rootScope.$new()
     @typeService = Type
     @scope.context = undefined
     spyOn(@typeService, 'index')

   describe '#home-page', ->
     beforeEach inject ($controller) ->
       $controller 'MyApp.Controller.MyCarsController', $scope: @scope
     it 'contains a list of types', ->
       expect(@typeService.index).toHaveBeenCalledWith({ ferrari_or_porsche : '', id : '' }, jasmine.any(Function))

     it "sets instance variables correctly", ->
       expect(@scope.ferrari_or_porsche).toBe ""
       expect(@scope.id).toBe ""

注意:我没有声明此解决方案的“规范性”。但它有效。 注意:API 端点当然在其他地方进行了广泛的测试。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-05-10
    • 2019-01-02
    • 1970-01-01
    • 2017-10-31
    • 1970-01-01
    • 2016-05-03
    相关资源
    最近更新 更多