Service Karma/Jasmine单元测试具有依赖关系的AngularJS服务

Service Karma/Jasmine单元测试具有依赖关系的AngularJS服务,service,angularjs,mocking,dependencies,jasmine,Service,Angularjs,Mocking,Dependencies,Jasmine,我是一个新手程序员,对AngularJS和单元测试实践都非常陌生。我花了几个小时试图找到解决办法,但我越来越困惑。如果有人能给我指出正确的方向,我将不胜感激。我会尽可能地描述 情况是这样的: 我在AngularJS(服务a)中创建了一个服务,它有两个功能。每个函数都向RESTAPI发出$HTTPGET请求,并返回包含JSON数据的$HTTPPromise对象。在这些函数中,URL是通过实现另一个非常简单的服务(服务B)构建的,该服务已作为依赖项注入到服务a中。我创建了服务B的模拟,以将其与所有依

我是一个新手程序员,对AngularJS和单元测试实践都非常陌生。我花了几个小时试图找到解决办法,但我越来越困惑。如果有人能给我指出正确的方向,我将不胜感激。我会尽可能地描述

情况是这样的:

我在AngularJS(服务a)中创建了一个服务,它有两个功能。每个函数都向RESTAPI发出$HTTPGET请求,并返回包含JSON数据的$HTTPPromise对象。在这些函数中,URL是通过实现另一个非常简单的服务(服务B)构建的,该服务已作为依赖项注入到服务a中。我创建了服务B的模拟,以将其与所有依赖项隔离开来。这两个服务都是在同一个名为“服务”的模块中定义的。在这种情况下,不需要这种依赖关系,但我只想了解它是如何工作的

使用Jasmine,我想为服务a构造一个单元测试,以确保它对API发出的请求被正确构造,并且如果返回正确的JSON数据,则有可能。同时,我不希望进行任何真正的API调用

这就是我所知道的:

'use strict'

angular.module("services")
  .service("ServiceA", ["$http", "ServiceB", ($http, ServiceB) ->

    #Uses underscore.js to set this default attribute
    defaults = withCredentials:true

    getVarset: (itemName, options={}) ->
      options.method = "GET"
      options.url = ServiceB.makeUrl("item/#{itemName}")

      $http _.defaults(options, defaults)

    getVarsets: (options = {}) ->
      options.method = "GET"
      options.url = ServiceB.makeUrl("items")

      $http _.defaults(options, defaults)

    getModelsForVarset: (itemName, options = {}) ->
      options.method = "GET"
      options.url = ServiceB.makeUrl("item/#{itemName}/prices")

      $http _.defaults(options, defaults)
  ])
'use strict'

angular.module('services')
  .service 'ServiceB', [ ->

    # Just return the string
    # This service builds the real URL, but I've removed this
    makeUrl: (Url) -> 
      "#{Url}"
  ]
$httpBackend mock是我需要能够对API进行假调用的东西,它提供了预期某些请求并返回指定结果的功能

我需要测试真正的服务A并注入我为服务B创建的模拟。我知道有很多方法可以使用Jasmine Spies和$provide实现这一点。我也看到过使用sinon.js的例子,我不确定哪种方法是最好的


我将在下面发布我的源代码,它是用CoffeeScript编写的

服务A:

'use strict'

angular.module("services")
  .service("ServiceA", ["$http", "ServiceB", ($http, ServiceB) ->

    #Uses underscore.js to set this default attribute
    defaults = withCredentials:true

    getVarset: (itemName, options={}) ->
      options.method = "GET"
      options.url = ServiceB.makeUrl("item/#{itemName}")

      $http _.defaults(options, defaults)

    getVarsets: (options = {}) ->
      options.method = "GET"
      options.url = ServiceB.makeUrl("items")

      $http _.defaults(options, defaults)

    getModelsForVarset: (itemName, options = {}) ->
      options.method = "GET"
      options.url = ServiceB.makeUrl("item/#{itemName}/prices")

      $http _.defaults(options, defaults)
  ])
'use strict'

angular.module('services')
  .service 'ServiceB', [ ->

    # Just return the string
    # This service builds the real URL, but I've removed this
    makeUrl: (Url) -> 
      "#{Url}"
  ]
服务B:

'use strict'

angular.module("services")
  .service("ServiceA", ["$http", "ServiceB", ($http, ServiceB) ->

    #Uses underscore.js to set this default attribute
    defaults = withCredentials:true

    getVarset: (itemName, options={}) ->
      options.method = "GET"
      options.url = ServiceB.makeUrl("item/#{itemName}")

      $http _.defaults(options, defaults)

    getVarsets: (options = {}) ->
      options.method = "GET"
      options.url = ServiceB.makeUrl("items")

      $http _.defaults(options, defaults)

    getModelsForVarset: (itemName, options = {}) ->
      options.method = "GET"
      options.url = ServiceB.makeUrl("item/#{itemName}/prices")

      $http _.defaults(options, defaults)
  ])
'use strict'

angular.module('services')
  .service 'ServiceB', [ ->

    # Just return the string
    # This service builds the real URL, but I've removed this
    makeUrl: (Url) -> 
      "#{Url}"
  ]

那么你是说你知道如何使用$provide/Jasmine间谍并正在寻找替代方案?我主要是使用$provide/spy方法进行模拟,到目前为止效果非常好

比如:

beforeEach(function() {

    // set up a default value for your mock
    bMock = {
        makeUrl: jasmine.createSpy('makeUrl() mock').andReturn('http://www....')
    }

    // use the $provide service to replace ServiceB
    // with your mock
    module('services', function($provide) {
        $provide.value('ServiceB', bMock);
    });

});

it('should do what its supposed to do', function() {
     // test...
});
然后,如果您想使用$httpBackend来模拟服务A中的http请求,您只需要使用$injector服务来获取$httpBackend,然后调用