Тестирование угловых $http внутри цепочки обещаний с мокко
У меня есть jsdom/mocha/chai, настроенный для углового тестирования бэкэнда.
У меня есть сервис, который по существу делает это (намеренно не публикует данные):
app.service('testService', ['config', '$http', function(config, $http) {
function getSpecificConfig(type) {
return config.getConfig()
.then(function(config) {
// config is coming back defined;
// $http timesout
return $http({method: 'post', url: 'http://localhost:2222/some/path', withCredentials: true});
})
.then(function(res) {
return res.data.config[type];
})
.catch(function(err) {
//handles err
});
};
return {
getConfig: getConfig
}
}]);
мой тест:
/* jshint node: true */
/* jshint esversion: 6 */
let helpers = require(bootstrapTest),
inject = helpers.inject,
config,
specificConfig,
mockResponse,
$httpBackend,
$rootScope;
//config service
require('config.js');
//testService I'm testing
require('testService');
beforeEach(inject(function($injector, _$httpBackend_) {
config = $injector.get('config');
specificConfig = $injector.get('testService');
$rootScope = $injector.get('$rootScope');
$httpBackend = _$httpBackend_;
$httpBackend.when('POST', 'http://localhost:2222/some/path')
.response(function(data) {
//would like this to fire
console.log('something happened');
mockResponse = {data: 'some data'};
return mockResponse;
});
}));
afterEach(function() {
$httpBackend.verifyNoOutstandingExpectations();
$httpBackend.verifyNoOutstandingRequest();
});
describe ('this service', function() {
beforeEach(function() {
$httpBackend.expect('POST', 'http://localhost:2222/some/path');
$rootScope.$apply(function() {
return specificConfig('something');
});
});
it ('returns the specific config', function() {
expect(mockResponse).to.equal('some data');
})
});
Проблема: при запуске теста config.getConfig () разрешается правильно, но $http приводит к истечению времени ожидания mocha (2000 мс), а ловушка afterEach генерирует неудовлетворенный запрос.
Мое понимание этого может быть совершенно неверным, поэтому, пожалуйста, не стесняйтесь обучить меня правильному подходу (вот мой подход):
1) требуют все необходимые зависимости.
2) внедрить их и настроить прослушиватель $httpBackend, который запускает тестовый ответ при срабатывании реального http.
3) $ rootScope. $ Apply () любые обещания, поскольку их разрешение связано с угловым жизненным циклом.
4) первый перед каждым устанавливает слушателя, второй перед каждым запускает службу, которая запускает $http, позволяя $httpBackend запускать и устанавливать mockResponse.
5) тестовая реакция на ответ.
1 ответ
Если вам нужно возвращать обещания в ваших ложных HTTP-запросах, вы можете использовать angular-mocks-async следующим образом:
var app = ng.module( 'mockApp', [
'ngMockE2E',
'ngMockE2EAsync'
]);
app.run( [ '$httpBackend', '$q', function( $httpBackend, $q ) {
$httpBackend.whenAsync(
'GET',
new RegExp( 'http://api.example.com/user/.+$' )
).respond( function( method, url, data, config ) {
var re = /.*\/user\/(\w+)/;
var userId = parseInt(url.replace(re, '$1'), 10);
var response = $q.defer();
setTimeout( function() {
var data = {
userId: userId
};
response.resolve( [ 200, "mock response", data ] );
}, 1000 );
return response.promise;
});
}]);