2013-07-24 1 views
28

После долгих чтений кажется, что рекомендуется использовать веб-службу от контроллера AngularJS, чтобы использовать фабрику и вернуть обещание от этого.

Здесь у меня простая фабрика, которая вызывает образец API.

myApp.factory('MyFactory', ['$http',function($http) { 
var people = { 
     requestPeople: function(x) { 
      var url = 'js/test.json'; 
      return $http.get(url); 
     } 
    }; 
return people; 
}]); 

И это, как я это называю в контроллере

myApp.controller('MyCtrl1', ['$scope', 'MyFactory', function ($scope, MyFactory) { 
     MyFactory.requestPeople(22).then(function(result) { 
      $scope.peopleList = result; 
     }); 
}]); 

В то время как это работает хорошо, я хотел бы быть в состоянии дразнить result, который передается в then когда называется. Это возможно?

Моя попытка пока ничего не произвела. Это моя попытка:

//Fake service 
var mockService = { 
    requestPeople: function() { 
     return { 
      then: function() { 
       return {"one":"three"}; 
      } 
     } 

    } 
}; 


//Some setup 
beforeEach(module('myApp.controllers')); 
var ctrl, scope; 

beforeEach(inject(function ($rootScope, $controller) { 
    scope = $rootScope.$new(); 

    ctrl = $controller('MyCtrl1', { $scope: scope, MyFactory: mockService }); 
})); 

//Test 
it('Event Types Empty should default to false', inject(function() { 
    expect(scope.peopleList.one).toBe('three'); 
})); 

ошибка, что я получаю при запуске это карма бегуна, является

TypeError: «не определено» не является объектом (оценка «scope.peopleList.one»)

Как я могу получить этот тест, работая с моими издеваемыми данными?

+0

Я читал об этом, но мой контроллер не берет $ http. Можете ли вы рассказать о том, что вы имеете в виду? – Mendhak

ответ

38

Я не думаю, что $ httpBackend - это то, что вы здесь, вы хотите, чтобы весь завод был издевался, не имея зависимости от $ http?

Посмотрите на $q, в частности на образец кода под заголовком Testing. Ваша проблема может быть решена с кодом, который выглядит следующим образом:

'use strict'; 

describe('mocking the factory response', function() { 

    beforeEach(module('myApp.controllers')); 

    var scope, fakeFactory, controller, q, deferred; 

    //Prepare the fake factory 
    beforeEach(function() { 
     fakeFactory = { 
      requestPeople: function() { 
       deferred = q.defer(); 
       // Place the fake return object here 
       deferred.resolve({ "one": "three" }); 
       return deferred.promise; 
      } 
     }; 
     spyOn(fakeFactory, 'requestPeople').andCallThrough(); 
    }); 

    //Inject fake factory into controller 
    beforeEach(inject(function ($rootScope, $controller, $q) { 
     scope = $rootScope.$new(); 
     q = $q; 
     controller = $controller('MyCtrl1', { $scope: scope, MyFactory: fakeFactory }); 
    })); 

    it('The peopleList object is not defined yet', function() { 
     // Before $apply is called the promise hasn't resolved 
     expect(scope.peopleList).not.toBeDefined(); 
    }); 

    it('Applying the scope causes it to be defined', function() { 
     // This propagates the changes to the models 
     // This happens itself when you're on a web page, but not in a unit test framework 
     scope.$apply(); 
     expect(scope.peopleList).toBeDefined(); 
    }); 

    it('Ensure that the method was invoked', function() { 
     scope.$apply(); 
     expect(fakeFactory.requestPeople).toHaveBeenCalled(); 
    }); 

    it('Check the value returned', function() { 
     scope.$apply(); 
     expect(scope.peopleList).toBe({ "one": "three" }); 
    }); 
}); 

Я добавил некоторые тесты вокруг того, что $ применять ли, я не знал, что, пока я не начал играть с этим!

Gog

+0

Это сработало отлично. Я пришел к чему-то подобному, но то, что мне не хватало, было «defer», возвращающее правильное значение, и теперь '$ scope.apply()' имеет больше смысла. – Mendhak

+0

У меня были успешные тесты на основе этого кода. Однако, перейдя к синтаксису «контроллер как», неясно, как изменить пройденный тест. Проблема заключается в том, что использование '' MyCtrl1 as foo'' является проблемой. Даже тесты 'not.toBeDefined' терпят неудачу с' TypeError: undefined не является функцией'. –

+1

В чем смысл выражения 'spyOn' здесь. Я удалил его из тестовых спецификаций, и тест все же прошел успешно. – Aakash

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