6

我正在尝试使用 Karma 和 Jasmine 对我的 AngularJS 应用程序进行单元测试。我想模拟$http服务。为此,我使用了 $httpBackend 方法。以下是我要测试的服务:

angular.module('MyModule').factory('MyService', function($http, $log, $parse, $q, $timeout, $filter, MyOtherService1, MyOtherService2){
var service = {};
   service.getSomething = function(id){
     return $http.get('/somePath/subpath/' + id);
   }
});

我对此服务的单元测试是:

describe("myTest", function(){
    var myService, $httpBackend, scope, mockMyOtherService1, mockMyOtherService2;

    var myResponse =
    {
        foo:'bar'
    };

    beforeEach(module("MyModule"));

    beforeEach(inject(function(_MyService_, $injector){

        $httpBackend = $injector.get('$httpBackend');
        myService = _MyService_;
        scope = $injector.get('$rootScope').$new();
        mockMyOtherService1 = $injector.get('MyOtherService1');
        mockMyOtherService2 = $injector.get('MyOtherService2');

    }));

    beforeEach(function(){
        //To bypass dependent requests
        $httpBackend.whenGET(/\.html$/).respond(200,'');
    });

    //If I uncomment the below afterEach block, the same error is shown at next line.
    /*afterEach(function() {
         $httpBackend.verifyNoOutstandingExpectation();
         $httpBackend.verifyNoOutstandingRequest();
     });*/

    //This test passes successfully
    it("should check if service is instantiated", function () {
        expect(myService).toBeDefined();
    });

    //This test passes successfully
    it("should expect dependencies to be instantiated", function(){
        expect($httpBackend).toBeDefined();
    });

    //The problem is in this test
    it("should get the getSomething with the provided ID", function() {
        $httpBackend.whenGET('/somePath/subpath/my_123').respond(200,myResponse);            
        var deferredResponse = myService.getSomething('my_123');

        //The error is shown in next line.
        $httpBackend.flush();      

        //If I comment the $httpBackend.flush(), in the next line, the $$state in deferredResponse shows that the Object that I responded with is not set i.e. it does not matches the 'myResponse'.
        expect(deferredResponse).toEqual(myResponse);

    });
});

这是一个紧急问题,我需要尽快得到帮助。我将非常感谢您的回答。

4

3 回答 3

1

您将从您的服务中得到承诺。因此,将您的测试代码更改为:

//The problem is in this test
it("should get the getSomething with the provided ID", function (done) {
  $httpBackend.expectGET('/somePath/subpath/my_123').respond(200,myResponse);
  var deferredResponse = myService.getSomething('my_123');

  deferredResponse.then(function (value) {
    expect(value.data).toEqual(myResponse);
  }).finally(done);

  $httpBackend.flush();
});
于 2015-11-23T13:33:23.027 回答
1

问题是我需要在我的规范文件中注入 $location,即使它们没有注入到服务中。注射后,一切正常!希望这可以帮助陷入相同情况的人。

于 2015-12-14T15:15:26.627 回答
1

我最近在将项目从 Angular 1.2 更新到 1.4 时遇到了这个问题。测试代码看起来像:

it('should call /something', function(){
    httpBackend.expectGET('/something').respond(200);
    scope.doSomething();
    httpBackend.flush();
});

错误是过去 10 次迭代的 infdig。它是由调用该.flush()方法引起的。我发现这似乎是因为在doSomething().

一旦我在某处doSomething()或内部方法中添加了一个承诺,infdig问题就消失了。

我怀疑——这是 100% 的猜测,所以不要让它影响你的开发——这是因为 httpBackend 做了一些诡计来等待承诺,这可能涉及反复消化直到有变化。由于没有承诺,所以没有变化 - 无限摘要。

于 2016-07-25T17:22:46.513 回答