如何使用Jasmine正确测试Angular的$ http成功和错误承诺

时间:2015-05-26 16:26:53

标签: angularjs unit-testing jasmine

我有这样的控制器:

$scope.signIn = (user) ->
      if user.email != '' and user.password != ''
        UserService.signIn(user)

我有这样的服务:

 signIn: (user) ->
        $http.post '/user/signin', user

        .success (data) ->
          AuthService.set 'email', data.user.local.email

        .success () ->
          $state.go 'auth.profile'

        .error () ->
          throw Error(err)

到目前为止我有这样的测试:

describe 'AuthController Unit Tests', ->

  beforeEach module('kreditorenApp')

  AuthController  = undefined
  scope           = undefined
  AuthService     = undefined
  UserService     = undefined
  $httpBackend    = undefined
  $controller     = undefined
  $location       = undefined
  user            = undefined
  HTTPInterceptor = undefined
  $alert          = undefined

  resUser =
    "status": "OK"
    "error": "Erfolgreich Authentifiztiert"
    "type": "success"
    "token": "TOKEN STRING"
    "user":
      "__v": 0
      "_id": "5512a0dfcbc8ea974647f493"
      "local":
        "password": "HASH STRING"
        "email": "dieter"


  beforeEach inject(($rootScope, _$controller_, _$httpBackend_, _UserService_, _AuthService_, _$location_, _$alert_, _HTTPInterceptor_) ->

    scope         = $rootScope.$new()
    $controller   = _$controller_
    $httpBackend  = _$httpBackend_
    $location     = _$location_
    UserService   = _UserService_
    AuthService   = _AuthService_
    HTTPInterceptor = _HTTPInterceptor_

    # Stubs
    #
    httpFake = () ->
      bla:
        "bla"

    userFake = () ->
      signIn:
        "SUCCESS"

    # Spies
    #
    spyOn(HTTPInterceptor, 'response').and.callFake(httpFake)
    # spyOn(UserService, 'signIn').and.callFake(userFake)

    $httpBackend.expectPOST('/user/signin', user).respond(200, {user":"local":"email":"emperorRudolf"})
    $httpBackend.expectGET('app/controller/auth/auth.html').respond(200)
    $httpBackend.expectGET('app/controller/auth/partials/profile.html').respond(200)

    AuthController = $controller('AuthController', $scope:scope)
  )

  afterEach ->
    $httpBackend.verifyNoOutstandingExpectation()
    $httpBackend.verifyNoOutstandingRequest()

  it 'should signIn user & ui-route to auth.profile & invoke HTTPInterceptor', ->

    # Tests
    #
    scope.signIn ({email:'mail', password:'pass'})
    $httpBackend.flush()

    #expect(HTTPInterceptor.response).toHaveBeenCalled
    #expect many more things later

测试失败

 TypeError: 'undefined' is not an object (evaluating 'data.user')

我想尽可能少地嘲笑。

编辑:数据对象始终未定义。我的测试无法访问或了解$http相当独特的.success方法。我该如何正确测试?

2 个答案:

答案 0 :(得分:1)

这是error的完成方式。获取对我们拒绝的承诺的引用,提供错误消息并捕获错误。我仍在使用.success promise,并在我运行后立即更新。我想我会切换到Sinon,因为这对于测试我的控制器/服务二人来说似乎很复杂。

describe 'AuthController Unit Tests', ->

  beforeEach module('myApp')

  UserService = undefined
  httpMock = undefined
  $q = undefined
  $scope = undefined

  beforeEach module('myApp', ($provide) ->
    httpMock = jasmine.createSpyObj('$http', ['post'])
    $provide.value('$http', httpMock)
    return
  )

  beforeEach inject((_$controller_, $rootScope, _$q_, _UserService_) ->
    $scope = $rootScope.$new()
    $controller = _$controller_
    $q = _$q_
    UserService = _UserService_

    AuthController = $controller('AuthController',
      $scope: $scope
    )
  )

  it 'should catch an error', ->

    errorMsg = 'Unauthorized'
    defer = $q.defer()
    defer.reject(errorMsg)
    httpMock.post.and.returnValue(defer.promise)

    UserService.signIn('1').catch (error) ->
      expect(error).toEqual(errorMsg)

    $scope.$digest();
    return

请注意return之后$provide.value('$http', httpMock)是强制性的,否则CoffeeScript会来困扰你。道具Simon Bailey's Angular Testing Cookbook为此提供帮助。

答案 1 :(得分:0)

您将帖子编码为/user/signin,并希望返回包含用户的响应正文:

 $http.post '/user/signin', user

    .success (data) ->
        AuthService.set 'email', data.user.local.email

但是当你嘲笑后端时,你会让它返回以下内容:

$httpBackend.expectPOST('/user/signin', user).respond(200, {"asd":"asd"})

因此,显然,尝试访问对象user.local.email上的{"asd":"asd"}无法正常工作。