将模拟注入到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创建的服务。

有人知道我可以如何嘲笑我的单元测试注入的服务吗?

谢谢

大卫


您可以使用$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期间发生在引擎盖下。 在这里设置mockDependency时,它可能很容易成为间谍。

感谢loyalBrown链接到伟大的视频。


我看待它的方式,不需要自己嘲笑服务。 简单地模拟服务的功能。 这样,您就可以在整个应用程序中为您的实际服务注入角色。 然后,根据需要使用Jasmine的spyOn函数来模拟服务上的功能。

现在,如果服务本身是一个函数,而不是一个可以使用spyOn的对象,还有另一种方法可以解决它。 我需要做到这一点,并找到一些对我来说非常有用的东西。 请参阅如何模拟角色服务是一种功能?


在Angular和Jasmine中,另一种帮助简化模拟依赖关系的方法是使用QuickMock。 它可以在GitHub上找到,并允许您以可重用的方式创建简单的模拟。 你可以通过下面的链接从GitHub克隆它。 自述文件很自我解释,但希望它可以在未来帮助其他人。

https://github.com/tennisgent/QuickMock

describe('NotificationService', function () {
    var notificationService;

    beforeEach(function(){
        notificationService = QuickMock({
            providerName: 'NotificationService', // the provider we wish to test
            moduleName: 'QuickMockDemo',         // the module that contains our provider
            mockModules: ['QuickMockDemoMocks']  // module(s) that contains mocks for our provider's dependencies
        });
    });
    ....

它会自动管理上面提到的所有样板文件,因此您不必在每次测试中都写出所有模拟注入代码。 希望有所帮助。

链接地址: http://www.djcxy.com/p/77555.html

上一篇: Injecting a mock into an AngularJS service

下一篇: How is AngularJS different from jQuery