How can I configure an angular app to use stub services on one server and real on another? I want to host my app on a super cheap php web server for demoing to a stakeholder. I could stub the external rest services but I haven't written any php for years and don't really want to. I would prefer to use stub angular services that can also be used for end to end tests. I want to do this with config rather than changing any code...
1 Answer
You can use $provide.value(...) in your config(...) block to achieve this:
angular.module('stub', []). // <- module that holds mock service
factory('appServiceMock', function() { // <- mock for appService that will be defined in app module
return {
getName: function() {
return 'Mock Service';
}
}
});
angular.module('app', ['stub']). // <- define app module depends on stub module
factory('appService', function() {
return {
getName: function() {
return 'Real Service';
}
}
}).
config(function($provide, appServiceMockProvider) { // <- only providers and constants may be injected to config block. appServiceMockProvider - is created by Angular automatically when you define factory('appServiceMock', ...).
$provide.value('appService', appServiceMockProvider.$get()); // <- get mock service from provider
}).
controller('appController', function($scope, appService) { // <- no changes in controller definition
$scope.name = appService.getName(); // <- will return 'Mock Service'
});
Plunker: http://plnkr.co/edit/b3vIh6aCGNami2m0Bgrz?p=preview
For your tests you can do the same thing (NOTE: you should include angular-mocks.js to be able to use module(...) and inject(...) in your tests):
describe('Test Scope', function() {
beforeEach(function(){
module('app', function($provide) {
$provide.value('appService', {
name: 'Mock Service'
});
});
});
it('should do something', inject(function(appService) {
expect(appService.name).toBeDefined();
}));
});
Besides of it AngularJS provides a lot of mocks for its services. You just need to include angular-mocks.js and it will override some angular built-it services and will add some other useful stuff. For example, if you use $http to access remote REST services than you can utilize $httpBackend to mock them:
it('should check REST service', inject(function($httpBackend, appServiceThatUseHttp) {
var response;
$httpBackend.resetExpectations();
$httpBackend.expect('GET', 'http://www.test.com/v1/things').respond({things: ['thing 1', 'thing 2']});
response = appServiceThatUseHttp.getThings(); // <- Assume that service puts parsed response body into it's property named data
$httpBackend.flush();
expect(response.data.things.length).toBe(2);
}));