2013-09-20 3 views
3

Я использую службу $httpBackend в модуле ngMock для имитации запроса GET. Из AngularJS documentation, вот пример контроллера:Как смоделировать сетевую задержку при модульном тестировании контроллера AngularJS?

// The controller code 
function MyController($scope, $http) { 
    var authToken; 

    $http.get('/auth.py').success(function(data, status, headers) { 
    authToken = headers('A-Token'); 
    $scope.user = data; 
    }); 

    $scope.saveMessage = function(message) { 
    var headers = { 'Authorization': authToken }; 
    $scope.status = 'Saving...'; 

    $http.post('/add-msg.py', message, { headers: headers }).success(function(response) { 
    $scope.status = ''; 
    }).error(function() { 
    $scope.status = 'ERROR!'; 
    }); 
    }; 
} 

и, вот соответствующий жасмин тест спецификации:

// testing controller 
describe('MyController', function() { 
    var $httpBackend, $rootScope, createController; 

    beforeEach(inject(function($injector) { 
    // Set up the mock http service responses 
    $httpBackend = $injector.get('$httpBackend'); 
    // backend definition common for all tests 
    $httpBackend.when('GET', '/auth.py').respond({userId: 'userX'}, {'A-Token': 'xxx'}); 

    // Get hold of a scope (i.e. the root scope) 
    $rootScope = $injector.get('$rootScope'); 
    // The $controller service is used to create instances of controllers 
    var $controller = $injector.get('$controller'); 

    createController = function() { 
    return $controller('MyController', {'$scope' : $rootScope }); 
    }; 
})); 


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


it('should fetch authentication token', function() { 
    $httpBackend.expectGET('/auth.py'); 
    var controller = createController(); 
    $httpBackend.flush(); 
}); 


it('should send msg to server', function() { 
    var controller = createController(); 
    $httpBackend.flush(); 

    // now you don’t care about the authentication, but 
    // the controller will still send the request and 
    // $httpBackend will respond without you having to 
    // specify the expectation and response for this request 

    $httpBackend.expectPOST('/add-msg.py', 'message content').respond(201, ''); 
    $rootScope.saveMessage('message content'); 
    expect($rootScope.status).toBe('Saving...'); 
    $httpBackend.flush(); 
    expect($rootScope.status).toBe(''); 
}); 

it('should send auth header', function() { 
    var controller = createController(); 
    $httpBackend.flush(); 

    $httpBackend.expectPOST('/add-msg.py', undefined, function(headers) { 
    // check if the header was send, if it wasn't the expectation won't 
    // match the request and the test will fail 
    return headers['Authorization'] == 'xxx'; 
    }).respond(201, ''); 

    $rootScope.saveMessage('whatever'); 
    $httpBackend.flush(); 
    }); 
}); 

Как написано выше, фиктивный запрос мгновенно реагирует при выполнении тестов. Я хотел бы установить задержку в ложном запросе GET. Это возможно? У меня есть чувство, что для достижения этой цели понадобится услуга $timeout.

Бонус Вопрос: Есть ли какие-либо недостатки в установке задержки как это? Это разумная вещь, чтобы сделать в модульном тесте AngularJS?

+1

о бонусном вопросе: http://superuser.com/questions/330501/how-can-i-simulate-a-slow-connection-or-limit-the-bandwidth-that-firefox-can-us I не думайте, что это то, что вы хотите иметь в модульном тесте. –

+0

@EduardGamonal: я буквально не хочу дросселировать браузер; должно быть достаточно углового 'window.setTimeout'. –

+2

Да, вы можете использовать таймаут, но вы должны тестировать две вещи: небольшую полосу пропускания и высокую задержку. вы можете сделать это с помощью iprelay + firefox throttle. Я думаю, что модульные тесты предназначены для тестирования ввода/вывода компонентов, а не того, насколько надежно оно работает в суровых условиях сети. –

ответ

2

Создание декоратора для $ httpBackend, как этот: http://endlessindirection.wordpress.com/2013/05/18/angularjs-delay-response-from-httpbackend/

Поместите это в ваших app.js, за 700 мс задержки во время каждого издевались или проходное ответ:

.config(function($provide) { 
    $provide.decorator('$httpBackend', function($delegate) { 
     var proxy = function(method, url, data, callback, headers) { 
      var interceptor = function() { 
       var _this = this, 
        _arguments = arguments; 
       setTimeout(function() { 
        callback.apply(_this, _arguments); 
       }, 700); 
      }; 
      return $delegate.call(this, method, url, data, interceptor, headers); 
     }; 
     for(var key in $delegate) { 
      proxy[key] = $delegate[key]; 
     } 
     return proxy; 
    }); 
}) 

Bonus Ответ: Я верить время - это не то, что вы проверите в модульном тесте. Но, конечно же, вам нужно протестировать ошибки сервера, поэтому издевательство над http идет удобно.

И я использую задержку, например, при прототипировании, это тоже допустимый сценарий.

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