Reputation:
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 composed with my app module:
angular.module('app', ['someModule', 'someOtherModule'])
Upvotes: 3
Views: 2790
Reputation: 336
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 comment 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!');
});
});
});
Upvotes: 1
Reputation: 54524
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
Upvotes: 6