Karma-Jasmine:意外请求:GET ...没有更多请求
Karma-Jasmine: Unexpected request: GET ... No more request expected
情况:
我正在 AngularJs 应用程序中测试两个不同的 http 调用。
有一个奇怪的行为。如果我分别测试每一个,而另一个临时注释掉(在控制器和测试中),每一个都可以正常工作并且测试通过。
但是如果我 运行 karma 当有两个测试时,它们都会失败,并给出以下错误消息:
Unexpected request: GET https://MY_DOMAIN_2.com/list_project
No more request expected
控制器:
.controller('TestController', function($scope, $http, $timeout) {
$scope.getLanguageList = function()
{
$http.get('http://MY_DOMAIN_1.org/languageList').then(function(resp)
{
$scope.language_list = resp.data;
},
function(err)
{
$scope.language_list = [];
})
}
$scope.language_list = [];
$scope.getLanguageList();
$scope.get_project_list = function()
{
$http.get('https://MY_DOMAIN_2.com/projectList').then(function(resp)
{
$scope.project_list = resp.data;
},
function(err)
{
$scope.project_list = [];
})
}
$scope.project_list = [];
$scope.get_project_list();
})
测试:
describe('Http requests tests', function() {
beforeEach(module('my_app.controllers'));
var $controller;
var $httpBackend;
var $scope;
var $timeout;
describe('Lists test', function()
{
beforeEach(angular.mock.http.init);
afterEach(angular.mock.http.reset);
beforeEach(inject(function(_$controller_, _$httpBackend_)
{
$controller = _$controller_;
$scope = {};
$httpBackend = _$httpBackend_;
}));
it('should load default language list', function (done)
{
$httpBackend.whenGET('http://MY_DOMAIN_1.org/languageList').passThrough();
var TestController = $controller('TestController', { $scope: $scope });
setTimeout(function()
{
expect($scope.language_list).not.toEqual([]);
done();
}, 1000);
});
it('should load default project list', function (done)
{
$httpBackend.whenGET('https://MY_DOMAIN_2.org/projectList').passThrough();
var TestController = $controller('TestController', { $scope: $scope });
setTimeout(function()
{
expect($scope.project_list).not.toEqual([]);
done();
}, 1000);
});
});
});
问题:
为什么我会收到该错误消息?
代码应该没问题,因为它们单独工作正常。我错过了什么吗?
谢谢!
不使用超时,同时测试:
it('should load default language list and the default project list', function (){
$httpBackend.whenGET('http://MY_DOMAIN_1.org/languageList').passThrough();
$httpBackend.whenGET('httpS://MY_DOMAIN_2.org/projectList').passThrough();
var TestController = $controller('TestController', { $scope: $scope });
$httpBackend.flush();
expect($scope.language_list).not.toEqual([]);
expect($scope.project_list).not.toEqual([]);
});
这里有一些指导和演示 http://plnkr.co/edit/Kp9C4S6oNVu1MM1YLb90?p=preview
您应该使用 $httpBackend.flush()
而不是 setTimeout()
。这样你就可以控制什么时候你的异步请求returns。它使测试更容易。
将您的 $httpBackend 和控制器拉出到 beforeEach 语句中。创建控制器后,它会触发两个 url。然后你可以单独评估它。当它在 it
语句中被隔离时,它不会调用另一个 $http 并抛出意外的 url 错误。
您还应该模拟 $http 请求的响应,而不是 passThrough。您并不总是会连接到互联网,并且响应可能会发生变化。所以让模拟数据看起来像你期望的那样。
另外,$httpBackend.whenGET('httpS://MY_DOMAIN_2.org/projectList')
请求的是不正确的url。它应该是一个小写的 s
和一个 .com
url。这是因为控制器正在请求
$http.get('https://MY_DOMAIN_2.com/projectList')
您需要将 setTimeout 和 done 属性 添加到您的刷新中以防止它
it('should get data in callback funcion', function (done) {
$httpBackend.whenGET(/\/my-endpoint/).respond(mockDataResponse);
apiFactory.getCurrencyFormat('en', function (res, err) {
expect(res.a).to.deep.equal(generalMock.a);
expect(res.b).to.deep.equal(generalMock.b);
});
setTimeout(function () {
done();
$httpBackend.flush();
}, 200);
});
情况:
我正在 AngularJs 应用程序中测试两个不同的 http 调用。
有一个奇怪的行为。如果我分别测试每一个,而另一个临时注释掉(在控制器和测试中),每一个都可以正常工作并且测试通过。
但是如果我 运行 karma 当有两个测试时,它们都会失败,并给出以下错误消息:
Unexpected request: GET https://MY_DOMAIN_2.com/list_project
No more request expected
控制器:
.controller('TestController', function($scope, $http, $timeout) {
$scope.getLanguageList = function()
{
$http.get('http://MY_DOMAIN_1.org/languageList').then(function(resp)
{
$scope.language_list = resp.data;
},
function(err)
{
$scope.language_list = [];
})
}
$scope.language_list = [];
$scope.getLanguageList();
$scope.get_project_list = function()
{
$http.get('https://MY_DOMAIN_2.com/projectList').then(function(resp)
{
$scope.project_list = resp.data;
},
function(err)
{
$scope.project_list = [];
})
}
$scope.project_list = [];
$scope.get_project_list();
})
测试:
describe('Http requests tests', function() {
beforeEach(module('my_app.controllers'));
var $controller;
var $httpBackend;
var $scope;
var $timeout;
describe('Lists test', function()
{
beforeEach(angular.mock.http.init);
afterEach(angular.mock.http.reset);
beforeEach(inject(function(_$controller_, _$httpBackend_)
{
$controller = _$controller_;
$scope = {};
$httpBackend = _$httpBackend_;
}));
it('should load default language list', function (done)
{
$httpBackend.whenGET('http://MY_DOMAIN_1.org/languageList').passThrough();
var TestController = $controller('TestController', { $scope: $scope });
setTimeout(function()
{
expect($scope.language_list).not.toEqual([]);
done();
}, 1000);
});
it('should load default project list', function (done)
{
$httpBackend.whenGET('https://MY_DOMAIN_2.org/projectList').passThrough();
var TestController = $controller('TestController', { $scope: $scope });
setTimeout(function()
{
expect($scope.project_list).not.toEqual([]);
done();
}, 1000);
});
});
});
问题:
为什么我会收到该错误消息? 代码应该没问题,因为它们单独工作正常。我错过了什么吗?
谢谢!
不使用超时,同时测试:
it('should load default language list and the default project list', function (){
$httpBackend.whenGET('http://MY_DOMAIN_1.org/languageList').passThrough();
$httpBackend.whenGET('httpS://MY_DOMAIN_2.org/projectList').passThrough();
var TestController = $controller('TestController', { $scope: $scope });
$httpBackend.flush();
expect($scope.language_list).not.toEqual([]);
expect($scope.project_list).not.toEqual([]);
});
这里有一些指导和演示 http://plnkr.co/edit/Kp9C4S6oNVu1MM1YLb90?p=preview
您应该使用
$httpBackend.flush()
而不是setTimeout()
。这样你就可以控制什么时候你的异步请求returns。它使测试更容易。将您的 $httpBackend 和控制器拉出到 beforeEach 语句中。创建控制器后,它会触发两个 url。然后你可以单独评估它。当它在
it
语句中被隔离时,它不会调用另一个 $http 并抛出意外的 url 错误。您还应该模拟 $http 请求的响应,而不是 passThrough。您并不总是会连接到互联网,并且响应可能会发生变化。所以让模拟数据看起来像你期望的那样。
另外,
$httpBackend.whenGET('httpS://MY_DOMAIN_2.org/projectList')
请求的是不正确的url。它应该是一个小写的s
和一个.com
url。这是因为控制器正在请求$http.get('https://MY_DOMAIN_2.com/projectList')
您需要将 setTimeout 和 done 属性 添加到您的刷新中以防止它
it('should get data in callback funcion', function (done) {
$httpBackend.whenGET(/\/my-endpoint/).respond(mockDataResponse);
apiFactory.getCurrencyFormat('en', function (res, err) {
expect(res.a).to.deep.equal(generalMock.a);
expect(res.b).to.deep.equal(generalMock.b);
});
setTimeout(function () {
done();
$httpBackend.flush();
}, 200);
});