【问题标题】:Karma/Jasmine Unit Testing an AngularJS Service with DependenciesKarma/Jasmine 单元测试具有依赖关系的 AngularJS 服务
【发布时间】:2013-06-26 17:55:47
【问题描述】:

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

情况是这样的:

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

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

这是我所知道的:

$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)
  ])

服务 B:

'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}"
  ]

【问题讨论】:

    标签: service angularjs mocking dependencies jasmine


    【解决方案1】:

    所以你是说你知道如何使用 $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,然后调用它的 .when(...) 进行设置, 啦http://docs.angularjs.org/api/ngMock.$httpBackend

    【讨论】:

      猜你喜欢
      • 2017-09-05
      • 1970-01-01
      • 1970-01-01
      • 2013-12-24
      • 2016-05-03
      • 2013-04-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多