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);
});