最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Exchanging module values in AngularJS test - Stack Overflow

programmeradmin0浏览0评论

I have a module with a greet factory attached to it:

angular.module('someModule', [])
  .factory('greet', function(name) {
    return function() {
      return 'Hi ' + name + '!';
    }
  });

This factory injects a name which is a value defined in some other module.

angular.module('someOtherModule', [])
  .value('name', 'example');

When testing this module, I would like to be able to change the value of my injectable name multiple times (once for each test) so that my tests can look something like:

// In my test file…

// Initialise the module I am testing `greet` upon, and mock the other module which has a `name` value
beforeEach(mocks.module('someModule', function ($provider) {
    $provider.value('name', 'Bob');
}));

var greet

beforeEach(mocks.inject(function ($injector) {
    greet = $injector.get('greet');
});

it('should say "Bob"', function () {
    expect(greet()).toBe('Hi Bob!');
});

// Now I need to change the `name` value to be "Bar" instead

it('should say "Bar"', function () {
    expect(greet()).toBe('Hi Bar!');
});

How is this possible?

The two modules are posed with my app module:

angular.module('app', ['someModule', 'someOtherModule'])

I have a module with a greet factory attached to it:

angular.module('someModule', [])
  .factory('greet', function(name) {
    return function() {
      return 'Hi ' + name + '!';
    }
  });

This factory injects a name which is a value defined in some other module.

angular.module('someOtherModule', [])
  .value('name', 'example');

When testing this module, I would like to be able to change the value of my injectable name multiple times (once for each test) so that my tests can look something like:

// In my test file…

// Initialise the module I am testing `greet` upon, and mock the other module which has a `name` value
beforeEach(mocks.module('someModule', function ($provider) {
    $provider.value('name', 'Bob');
}));

var greet

beforeEach(mocks.inject(function ($injector) {
    greet = $injector.get('greet');
});

it('should say "Bob"', function () {
    expect(greet()).toBe('Hi Bob!');
});

// Now I need to change the `name` value to be "Bar" instead

it('should say "Bar"', function () {
    expect(greet()).toBe('Hi Bar!');
});

How is this possible?

The two modules are posed with my app module:

angular.module('app', ['someModule', 'someOtherModule'])
Share Improve this question edited Aug 15, 2013 at 14:25 asked Aug 15, 2013 at 13:14 user1082754user1082754
Add a ment  | 

2 Answers 2

Reset to default 6

You can use $provide.value('name', 'Bob'); to inject the value.

var myApp = angular.module('myApp', []);

myApp.factory('greet', function (name) {
    return function () {
        return 'Hi ' + name + '!';
    }
});

myApp.value('name', 'example');

describe('myApp', function () {
    beforeEach(angular.mock.module('myApp'));

    it('should say "Bob"', function () {
        module(function ($provide) {
            $provide.value('name', 'Bob');
        });
        angular.mock.inject(function ($injector) {
            var greet = $injector.get('greet');
            expect(greet()).toBe('Hi Bob!');
        })
    });

    it('should say "Bar"', function () {
        module(function ($provide) {
            $provide.value('name', 'Bar');
        });
        angular.mock.inject(function ($injector) {
            var greet = $injector.get('greet');
            expect(greet()).toBe('Hi Bar!');
        })
    });
});

I created a demo for you and hope it can shed some light!

Updated: demo

Demo

I was able to get this working, but I had to make a slight change to how the name dependency was injected (pointed out in the ment below). Given the app code:

angular.module("app", ["some", "other"]);

angular.module("some", []).factory('greet', function(name) { // name injected here
  return function() { // the name dependency moved from here up one function signature
    return 'Hi ' + name + '!';
  };
});

angular.module("other", []).value('name', 'example');

This is as DRY as I could make the test:

describe("greet", function() {

  var provide = injector = greet = undefined;

  beforeEach(function() {
    module('app', function($provide) {
      provide = $provide;
    });
    inject(function($injector) {
      injector = $injector;
    });
    greet = function() {
      return injector.get('greet')();
    };
  });

  describe("#greet", function() {
    it("says Hi Bob", function() {
      provide.value('name', 'Bob');
      expect(greet()).toBe('Hi Bob!');
    });

    it("says Hi Biff", function() {
      provide.value('name', 'Biff');
      expect(greet()).toBe('Hi Biff!');
    });
  });

});
发布评论

评论列表(0)

  1. 暂无评论