0

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 1

1

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);
}));
Sign up to request clarification or add additional context in comments.

4 Comments

So almost there but I can't figure out how to get my stub (which is in a stub services module) into my app config. I tried to use StubServiceProvider.$get[1]().
@shmish111 I've updated original post and plunk with example of using mock service defined in another module.
So close, but now it seems using $provide.value the angular $http service isn't injected into the service. Do I need to add some sort of manual injection at this point?
I've been playing around but I don't really understand the DI enough: $provide.value('SearchesService', StubSearchesServiceProvider.$get[2]($http.$get[6],$q.$get[2]));

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.