猿问

将模拟注入AngularJS服务

我写了一个AngularJS服务,我想对其进行单元测试。


angular.module('myServiceProvider', ['fooServiceProvider', 'barServiceProvider']).

    factory('myService', function ($http, fooService, barService) {


    this.something = function() {

        // Do something with the injected services

    };


    return this;

});

我的app.js文件已注册:


angular

.module('myApp', ['fooServiceProvider','barServiceProvider','myServiceProvider']

)

我可以测试DI是否像这样工作:


describe("Using the DI framework", function() {

    beforeEach(module('fooServiceProvider'));

    beforeEach(module('barServiceProvider'));

    beforeEach(module('myServiceProvder'));


    var service;


    beforeEach(inject(function(fooService, barService, myService) {

        service=myService;

    }));


    it("can be instantiated", function() {

        expect(service).not.toBeNull();

    });

});

这证明了可以通过DI框架创建服务,但是接下来我要对服务进行单元测试,这意味着要模拟注入的对象。


我该怎么做呢?


我尝试将模拟对象放入模块中,例如


beforeEach(module(mockNavigationService));

并将服务定义重写为:


function MyService(http, fooService, barService) {

    this.somthing = function() {

        // Do something with the injected services

    };

});


angular.module('myServiceProvider', ['fooServiceProvider', 'barServiceProvider']).

    factory('myService', function ($http, fooService, barService) { return new MyService($http, fooService, barService); })

但是后者似乎停止了DI所创建的所有服务。


有人知道如何模拟单元测试的注入服务吗?


狐的传说
浏览 567回答 3
3回答

MMMHUHU

您可以使用来将模拟注入服务中$provide。如果您具有以下具有依赖项的服务,该服务具有名为getSomething的方法:angular.module('myModule', [])  .factory('myService', function (myDependency) {        return {            useDependency: function () {                return myDependency.getSomething();            }        };  });您可以按如下方式注入myDependency的模拟版本:describe('Service: myService', function () {  var mockDependency;  beforeEach(module('myModule'));  beforeEach(function () {      mockDependency = {          getSomething: function () {              return 'mockReturnValue';          }      };      module(function ($provide) {          $provide.value('myDependency', mockDependency);      });  });  it('should return value from mock dependency', inject(function (myService) {      expect(myService.useDependency()).toBe('mockReturnValue');  }));});请注意,由于有调用,$provide.value因此实际上不需要在任何地方显式注入myDependency。它发生在注入myService的过程中。在此处设置嘲讽依赖时,它可能同样容易成为间谍。

智慧大石

从我的角度来看,无需自己模拟服务。只需在服务上模拟功能。这样,您就可以像在整个应用程序中一样对您的真实服务进行有角度的注入。然后,使用Jasmine的spyOn功能根据需要在服务上模拟功能。现在,如果服务本身是一个函数,而不是可以使用的对象spyOn,则还有另一种解决方法。我需要执行此操作,然后发现一些对我来说非常有效的方法。

精慕HU

除了John Galambos的回答:如果您只想模拟服务的特定方法,则可以这样做:describe('Service: myService', function () {  var mockDependency;  beforeEach(module('myModule'));  beforeEach(module(function ($provide, myDependencyProvider) {      // Get an instance of the real service, then modify specific functions      mockDependency = myDependencyProvider.$get();      mockDependency.getSomething = function() { return 'mockReturnValue'; };      $provide.value('myDependency', mockDependency);  });  it('should return value from mock dependency', inject(function (myService) {      expect(myService.useDependency()).toBe('mockReturnValue');  }));});
随时随地看视频慕课网APP
我要回答