Angular Jasmine(1.3)控制器模拟服务测试

时间:2014-09-26 23:50:28

标签: angularjs unit-testing karma-jasmine

这里可能有太多这样的问题,但我找不到任何一个好的解决方案。 在我看来,这个问题应该太常见了。 脏伪代码: Acontroller

app.controller('Acontroller',function($scope,$q, Aservice){

  $scope.someScopeVariable = null;

  function refresh(){
    $q.all([
    Aservice.getCollectionA().then(function(results){
      return $scope.collectionA = results}),
    Aservice.getCollectionB().then(function(results){
      return $scope.collectionB = results})
     ]);
    };

    $scope.someScopeFunction = function(){
       Aservice.someServerUpdateCall().then(function(){
         refresh().then(function(){
           $scope.someScopeVariable = 'woot'
         }
       }
     }
 })

这真的写的真的很差吗?我在我的光头上撕掉剩余的头发,试图测试someScopeFunction。

你会如何测试? (关于业力的茉莉花(1.3))

我可以测试承诺的第一层,但我不能断言调用刷新函数。我可以嘲笑这项服务,但是我有一段时间在这个刷新功能上得到间谍。我会假设我必须实例化控制器(找到类似的解决方案),虽然这看起来有点疯狂。

所以(原谅咖啡记录):

describe 'Acontroller', ->
  mockService = {}
  aResponseObject =
    a:1
    b:2
  beforeEach -> module('app')

  beforeEach inject ($controller,$q, $rootScope) ->

    emptyPromise = ->
      defer = $q.defer
      defer.resolve()
      defer.promise


    responsePromise = ->
      defer = $q.defer()
      defer.resolve([aResponseObject],[aResponseObject])
      defer.promise

    mockService.getCollectionA = jasmine.createSpy('getCollectionA').andReturn responsePromise()
    mockService.getCollectionB = jasmine.createSpy('getCollectionB').andReturn responsePromise()
    mockService.someServerUpdateCall = jasmine.createSpy('someServerUpdateCall').andReturn emptyPromise()
    scope = $rootScope.$new()
    $controller 'Acontroller',
      $scope: scope
      Aservice: mockService

    $rootScope.$apply  ## resolve promises

  describe 'someScopeFunction', ->

    it 'should call Aservice with someServerUpdateCall', ->

      scope.someScopeFunction()
      scope.$digest
      expect(Aservice.someSererUpdateCall).toHaveBeenCalled() ##this should work

这种期望很好,虽然确认下一次刷新是我不知所措的地方。看到它与范围无关,我认为我必须实例化Controller?

我玩过其他策略,包括:

done = false
refresh = jasmine.createSpy('refresh')

scope.someScopeFunction().then() -> done = true

waitsFor -> done

runs ->
  scope.$apply ->
    expect(refresh).toHaveBeenCalled()

无济于事,承诺未得到解决。

我听说Mocha让异步调用变得更加直接,但我真的害怕尝试重新开始。

1 个答案:

答案 0 :(得分:0)

所以,我想我已经明白了。 我改变了作用域上的原始函数来代替注入refresh()函数。 然后在测试中注入间谍后,在范围内调用$ digest,返回一个promise。

$scope.someScopeFunction = (refreshFn=refresh)
  Aservice.someServerUpdateCall().then ->
    refreshFn().then ->
      $scope.someScopeVariable = 'woot'

然后测试将是:

describe 'Acontroller', ->

  mockService = {}
  mocks = {}
  aResponseObject =
    a:1
    b:2
  beforeEach -> module('app')

  beforeEach inject ($controller,$q, $rootScope) ->

    mocks.emptyPromise = ->
      defer = $q.defer
      defer.resolve()
      defer.promise


    mocks.responsePromise = ->
      defer = $q.defer()
      defer.resolve([aResponseObject],[aResponseObject])
      defer.promise

    mockService.getCollectionA = jasmine.createSpy('getCollectionA').andReturn mocks.responsePromise()
    mockService.getCollectionB = jasmine.createSpy('getCollectionB').andReturn mocks.responsePromise()
    mockService.someServerUpdateCall = jasmine.createSpy('someServerUpdateCall').andReturn mocks.emptyPromise()

    scope = $rootScope.$new()

    $controller 'Acontroller',
      $scope: scope
      Aservice: mockService

    $rootScope.$apply  ## resolve promises

  describe 'someScopeFunction', ->

    it 'should call refresh() after someServerUpdateCall', ->
      refresh = jasmine.createSpy('refresh').andReturn(mocks.emptyPromise())
      scope.someScopeFunction(refresh)
      scope.$digest ->
        expect(refresh).toHaveBeenCalled()