Как издеваться над сервисом в angularAMD с помощью karma/jasmine?

У меня есть проект, использующий AngularAMD/RequireJS/Karma/Jasmine, у меня есть базовая конфигурация, все работает, большинство модульных тестов выполняются и проходят успешно.

Я не могу правильно ввести имитацию службы, используя angular.mock.module или angularAMD.value().

У меня есть:

// service definition in services/MyService.js
define(['app'], 
       function(app) {
           app.factory('myService', [ '$document', function($document) {
               function add(html) {
                   $document.find('body').append(html);
               }
               return { add: add }; 
           }]);
       }
);


// test
define(['angularAMD', 'angular-mocks', 'app', 'services/MyService'],
       function(aamd, mocks, app) {
           describe('MyService', function() {
               var myBodyMock = {
                   append: function() {}
               };
               var myDocumentMock = {
                   find: function(sel) {
                       // this never gets called 
                       console.log('selector: ' + sel);
                       return myBodyMock; 
                   }
               }; 
               var svc;
               beforeEach(function() {
                   // try standard way to mock a service through ng-mock
                   mocks.module(function($provide) {
                       $provide.value('$document', myDocumentMock);
                   });
                   // hedge my bets - try overriding in aamd as well as ng-mock
                   aamd.value('$document', myDocumentMock);              
               });
               beforeEach(function() { 
                   aamd.inject(['myService', 
                               function(myService) {
                                   svc = myService;
                               }]);
               });
               it('should work', function() {
                   // use svc expecting it to have injected mock of $document.
                   spyOn(myDocumentMock, 'find').andCallThrough();
                   spyOn(myBodyMock, 'append');
                   svc.add('<p></p>');
                   expect(myDocumentMock.find).toHaveBeenCalledWith('body');
                   expect(myBockMock.append).toHaveBeenCalledWith('<p></p>');
               });
           });
       }
);

Кто-нибудь знает, где я ошибаюсь? Любая помощь приветствуется.


person evil-dr-nick    schedule 17.10.2014    source источник
comment
взгляните на angularamd git, там есть несколько хороших тестовых примеров.   -  person z.a.    schedule 08.01.2015


Ответы (2)


Angular не является асинхронным, я думаю, что это не очень хорошая идея, чтобы использовать оба. Если вы пытаетесь найти хороший метод модульности, хорошо, но используйте оптимизатор RequireJS для создания всего, прежде чем размещать это в своем браузере, и что касается тестов, я думаю, вы можете просто использовать оптимизатор RequireJS для создания своих модулей до того, это позволит вам освободиться от «среды CommonJS даже в тестах».

person Victor Queiroz    schedule 26.01.2015

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

Верхняя строка моих тестовых файлов всегда выглядит примерно так:

var bodyMock, svcMock, foo, бар

Затем в beforeEach я устанавливаю значения

Изменить: поскольку bodyMock является только переменной области видимости, в тот момент, когда тесты фактически выполняются, и браузер ищет объект bodyMock, он ничего не может найти.

person TVG    schedule 23.05.2016