2015-12-22 3 views
1

Как я могу проверить эту директиву, которая делает вызов $ http на MyService? Как правильно высмеивать или шпионить за MyService?Единичный тест Угловая директива с инжектированным сервисом

angular.module('example') 
    .directive('myDirective', ['MyService', function(MyService) { 
     return { 
     restrict: 'E', 
     replace: true, 
     templateUrl: 'templates/myDirective.html', 
     scope: { 
      name: '@', 
      required: '=' 
     }, 
     link: function(scope, el, attrs, billingCtrl) { 
      scope.data = []; 

      MyService.get() 
      .then(function(res) { 
       scope.data = res; 
      }); 
     } 
     }; 
    }]); 

Мой тест:

describe('Directive: <my-directive>', function() { 
    // setup code 
    beforeEach(module('example')); 

    var element; 
    var compile; 
    var scope; 
    var compiledElementScope; 
    var validTemplate = '<my-directive ng-model="testModel" name="test"></my-directive>'; 
    var MyService = { get: function() {} }; 
    var $q; 

    function getCompiledElement(template) { 
     var compiledElement; 

     compiledElement = compile(template || validTemplate)(scope); 
     scope.$digest(); 

     return compiledElement; 
    } 

    beforeEach(function() { 
     module(function($provide) { 
     $provide.value('MyService', MyService); 
     }); 

     inject(function($compile, $rootScope, _$q_) { 
     compile = $compile; 
     scope = $rootScope.$new(); 
     $q = _$q_; 
     }); 

    }); 

    describe('my directive', function() { 
     var element; 

     beforeEach(function() { 
     element = getCompiledElement(validTemplate); 
     }); 

     it('should make a call to MyService and update scope.data', function() { 
     // how do I asset the following 
     expect(scope.data).toEqual(...); 
     }); 
    }) 
    }); 

ответ

1

Вместо того, чтобы писать var MyService = { get: function() {} }; создать объект шпиона внутри beforeEach где вы претендуете фиктивный службу к провайдеру.

Что-то вроде этого должно работать: var MyService;

beforeEach(function() { 
    MyService = jasmine.createSpyObj('MyService', ['get']); 

    MyService.get = jasmine.createSpy('get').and.callFake(function() { 
     return { 
      then: function (callback) { 
       callback(<RETURN_DATA>); 
       return this; 
      } 
     }; 
    }); 

    module(function($provide) { 
    $provide.value('MyService', MyService); 
    }); 

    ... 

}); 

Для <RETURN_DATA> просто вернуть фиктивный результат вы ожидаете быть сохранены в scope.data.

0

Вы должны использовать службу ng-mock $ httpBackend.

Эта услуга позволяет вам ОЖИДАТЬ http-запрос, который нужно сделать, и высмеять ответ.

Если запрос не выполнен, тест не выполняется.

$ httpBackend.when ... это говорит, что если запрос http сделан, тогда ответьте следующим образом ... нет никакого ожидания и, следовательно, если запрос не будет выполнен, тест не будет терпеть неудачу.

$ httpBackend.flush() говорит, что делать любые ожидающие запросы сейчас. Он не сработает, если ожиданий не будет.

Не забудьте ...

afterEach(function() { 
    httpBackend.verifyNoOutstandingExpectation(); 
    httpBackend.verifyNoOutstandingRequest(); 
}); 

Наконец, $ httpBackend будет жаловаться, если запросы делаются для HTML-файлов динамически. Чтобы избежать этой предварительной нагрузки всех HTML файлы в вашем karma.conf.js

preprocessors: { 
     'src/**/!(*spec)*.js': ['coverage'], 
     'dest/**/*.html': ['ng-html2js'] 
    }, 
    ngHtml2JsPreprocessor: { 
     stripPrefix: 'dest/', 
     moduleName: 'ngHtmlFiles' 
    }, 
    coverageReporter: { 
     type: 'html', 
     dir: 'coverage' 
    }, 
    files: [ 
     'dest/vendor.min.js', 
     'bower_components/angular-mocks/angular-mocks.js', 
     'src/**/*.js', 
     'dest/**/*.html' 
    ] 

Я знаю, что эта настройка конфигурации является болью, но если вы хотите следовать отраслевой практике, то вы должны получить эту работу :)

Смежные вопросы