karma/angularjs, как протестировать блок запуска с сервисом

Этот пост следует за этим I' я разместил другую тему с более простым примером

код для тестирования

 'use strict';

    var app = angular.module('myApp', []);
    app.run(function ($rootScope, Menus) {

        var menus = [
        {
            'permission': null,
            'title': 'Home',
            'link': 'home'
        },
        {
            'permission': 'users',
            'title': 'User',
            'link': 'user_actions.list'
        }
        ];

        $rootScope.menus = [];

        function queryMenu(menus) {
            Menus.query(menus).then(
                function (result) {
                    $rootScope.menus = result.data; 
                },
                function (reason) {
                    throw new Error(reason);
                }
                );
        }
        $rootScope.valueSetInRun = 555;
        queryMenu(menus);
    });
    app.factory('Menus',  function($http) {
        return {
            query : function(menus){
                return $http.get('menus.json');
            }
        }; 
    });
    app.factory('UserFactory', function($http){
        return $http.get('users.json')
    });
    app.controller('MainCtrl', function($scope, UserFactory) {
        $scope.users = [];
        $scope.text = 'Hello World!';
        UserFactory.then(function(data){
            $scope.users =  data.data;
        });
    });

контрольная работа

'use strict';

describe('Run', function() {
    beforeEach(module('myApp'));
   var $httpBackend;
    beforeEach(inject(function($rootScope,_$httpBackend_) {
        $httpBackend = _$httpBackend_;
        console.log('beforeEach');
    }));

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

    it('should allow me to test the run() block', inject(function ($rootScope,$httpBackend) {
        console.log('it block');
        // Doesn't work take a look at https://stackoverflow.com/questions/25363969/karma-angularjs-how-to-test-run-block-with-an-asynchronous-service
        $httpBackend.when('GET', 'menus.json').respond([{id: 1, name: 'Bob'}, {id:2, name: 'Jane'}]);
       $httpBackend.flush();
       expect( $rootScope.valueSetInRun ).toBe(555);
       console.log($rootScope.menus);
  }));
}); 

describe('MainCtrl', function(){
    var scope, $httpBackend;//we'll use these in our tests

    //mock Application to allow us to inject our own dependencies
    beforeEach(module('myApp'));
    //mock the controller for the same reason and include $rootScope and $controller
    beforeEach(inject(function( $controller,_$rootScope_, _$httpBackend_){
        $httpBackend = _$httpBackend_;

        $httpBackend.when('GET', 'users.json').respond([{id: 1, name: 'Bob'}, {id:2, name: 'Jane'}]);

        //create an empty scope
        scope = _$rootScope_.$new();
        //declare the controller and inject our empty scope
        $controller('MainCtrl', {$scope: scope});
        $httpBackend.flush();
    }));

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

    it('should have variable text = "Hello World!"', function(){
       expect(scope.text).toBe('Hello World!'); 
    });

    it('should fetch list of users', function(){
       //expect(scope.users.length).toBe(2);
       //expect(scope.users[0].name).toBe('Bob');
    });
});

которые дают мне эту ошибку

**Error: Unexpected request: GET menus.json
No more request expected**

END UP см. ответ @scarIz

beforeEach(module('myApp'));
var $httpBackend;
beforeEach(inject(function( _$httpBackend_) {
    $httpBackend = _$httpBackend_;
    $httpBackend.when('GET', 'menus.json').respond([{
        id: 1, 
        name: 'Bob'
    }])
    $httpBackend.flush();
}));
afterEach(function() {
    $httpBackend.verifyNoOutstandingExpectation();
    $httpBackend.verifyNoOutstandingRequest();
});
describe('Init', function() {

    describe('MainCtrl', function(){
        var scope, $httpBackend,$rootScope;//we'll use these in our tests

        //mock Application to allow us to inject our own dependencies

        //mock the controller for the same reason and include $rootScope and $controller
        beforeEach(inject(function( $controller,_$rootScope_, _$httpBackend_){
            $httpBackend = _$httpBackend_;

            $httpBackend.when('GET', 'users.json').respond([{
                id: 1, 
                name: 'Bob'
            }, {
                id:2, 
                name: 'Jane'
            }]);
            $rootScope = _$rootScope_;
            //create an empty scope
            scope = _$rootScope_.$new();
            //declare the controller and inject our empty scope
            $controller('MainCtrl', {
                $scope: scope
            });
            $httpBackend.flush();
        }));

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

        it('should have variable text = "Hello World!"', function(){
            expect(scope.text).toBe('Hello World!'); 
        });

        it('should fetch list of users', function(){
            expect(scope.users.length).toBe(2);
            expect(scope.users[0].name).toBe('Bob');
             expect( $rootScope.valueSetInRun ).toBe(555);
           console.log($rootScope.menus);
        });
    });
}); 

person Whisher    schedule 19.08.2014    source источник


Ответы (1)


Причина вашей ошибки в том, что Menus.query будет запускаться перед каждым тестом, который вы выполняете для модуля myApp, как он вызывается в конфигурации модуля .run(). Хотя вы предоставили определение серверной части в наборе тестов Run, вы не сделали этого для MainCtrl.

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

beforeEach(inject(function($httpBackend) {
  $httpBackend.when('GET', 'menus.json').respond([{id: 1, name: 'Bob'}])
  $httpBackend.flush();
}));
person scarlz    schedule 20.08.2014
comment
@scarlz огромное спасибо :) извините за беспокойство, но не могли бы вы взглянуть на stackoverflow.com/questions/25363969/ и тест gist.github.com/whisher/bc9ff302acd818b7632f ? Я применил тот же код, но с ui-router он не работает, и мне интересно, как это исправить ^^ - person Whisher; 20.08.2014