0

I created an angular custom directive with a service called scriptingService in it. The goal is to mock the service call out with a spyOn. This is part of the test:

 beforeEach(inject(function ($rootScope, $compile,_scriptingService_) {
      scope = $rootScope.$new();
      scope.row = 1;

      scriptingService = _scriptingService_;
      Restangular = _Restangular_;

      spyOn(Restangular, 'all').and.callThrough();

      spyOn(scriptingService, 'getScript').and.callThrough();

      element = angular.element('<ul id="rows" ui-list="row">');
      $compile(element)(scope);
      scope.$digest();
    }));

This is the directive code:

.directive('uiList', [
    function(scriptingService) {
        return {
            scope: {
                lengthModel: '=uiList'
            },
            link: function(scope, elm, attrs) {
                scope.$watch('lengthModel', function(newVal) {
                    scope.test=2;
                    console.log('kut');

                    scriptingService.getScript(request).then(function(scripts){
                        scope.scripts = scripts;
                    });

                });
            }
        };
    }
]);

However I am getting an error:

RestangularProvider <- Restangular <- scriptingService

How can I mock the scriptingService and make sure the method was called? Plunker ref:http://plnkr.co/edit/CDc7EV?p=preview

bier hier
  • 20,970
  • 42
  • 97
  • 166
  • Your plunkr has a few issues: old jasmin version combined with new syntax, and.callThrough() doesn't work in 1.3.1 (update jasmin or use andCallThrough()) and your scriptingService doesn't exist in the plunkr. The error "Unknown Provider" on the plunkr is expected as there is no such service registered with the module. – Frederik Prijck Feb 27 '16 at 23:56
  • I updated the plunkr and added the scriptService. I mocked out the Restangular but still getting an error:Error: Unknown provider: RestangularProvider <- Restangular <- scriptingService – bier hier Feb 28 '16 at 00:10
  • I can't see it on http://plnkr.co/edit/uhyzg6?p=preview – Frederik Prijck Feb 28 '16 at 01:05
  • sorry just updated the link:http://plnkr.co/edit/CDc7EV?p=preview – bier hier Feb 28 '16 at 01:06
  • In my opinion, the provided script isn't a good unit-test, are you testing a directive compilation? You need to mock everything else, included restangular. You don't need for a `callThrough`... you need to respond fake with the expected data... this in order to avoid test-failing if there are errors in your service. – Hitmands Feb 29 '16 at 16:50

1 Answers1

0

There are a couple of issues here:

  1. Like the comment said above, you need to use a newer version of jasmine for callThrough functionality, but also Restangular requires underscore, so that needs to be referenced as well in your html file.

  2. Also, the dependency injection needed to be fixed for your directive, because it was not able to inject scriptingService properly, which never allowed it to call scriptingService.getScript since scriptingService was undefined. The issue is that

    [ function(scriptingService) {}]
    

    will not work to inject scriptingService into uiList. It just ends up being undefined.

    It needs to either be

    ['scriptingService', function(scriptingService) {}]
    

    OR

    function(scriptingService) {}
    

    For reference: https://docs.angularjs.org/guide/di#dependency-annotation

  3. request is never defined when it's gets used in this code, I'm not sure what it's supposed to be.

    scriptingService.getScript(request).then(function(scripts) {
     scope.scripts = scripts;
    });
    
  4. After fixing these issues, the test was still failing, saying Error: Unexpected request: GET /scripting.

    I was able to fix this by injecting $httpBackend (which is a service for mocking http calls in angular) into the tests and expecting a request. So I changed

    inject(function ($rootScope, $compile,_scriptingService_,_Restangular_)
    

    TO

    inject(function ($rootScope, $compile,_scriptingService_,_Restangular_, $httpBackend)
    

    and added this

    $httpBackend.expectGET("/scripting").respond([]);
    

    after the spyOn's, then the test passed. I'm not sure exactly what this http call is supposed to return, but this is just an example of how you could test it.

    For reference: https://docs.angularjs.org/api/ngMock/service/$httpBackend

CShark
  • 1,562
  • 1
  • 16
  • 27