Javascript 如何在AngularJS中为$http promise创建单元测试

Javascript 如何在AngularJS中为$http promise创建单元测试,javascript,angularjs,unit-testing,karma-jasmine,Javascript,Angularjs,Unit Testing,Karma Jasmine,我有一个带有函数的服务,它可以使用$http和promise。我想用jasmine创建一个单元测试 account.service('AccountService', ['$q', '$http', function ($q, $http) { this.getServerDataForUrl = function (url) { var def = $q.defer(); $http.get(url) .success(f

我有一个带有函数的服务,它可以使用$http和promise。我想用jasmine创建一个单元测试

account.service('AccountService', ['$q', '$http', function ($q, $http) {
    this.getServerDataForUrl = function (url) {
         var def = $q.defer();
         $http.get(url)
              .success(function (data) {
                   if (data) {
                      def.resolve(data);
                   } else {
                      def.reject();
                   }
               })
               .error(function (error) {
                   if (data) {
                      def.resolve(data);
                   } else {
                      def.resolve();
                   }
                });
         return def.promise;
    };
}]);
更新:在回调时更改某些代码。
我已经搜索过了,但它没有给我这样的功能。有人给我举一些例子来创建关于它的单元测试吗。我认为这个函数很简单。谢谢。

在规范中创建一个变量,该变量保存AccountService实例的引用,并使用angular inject函数将其实例化

现在,您可以使用jasmine间谍来测试功能,或者使用marchers来测试服务公共成员

    var AccountSvs = undefined;
    beforeEach(inject(function (AccountService) {
    AccountSvs = AccountService;
    }));

    it('..', function(){
      expect(AccountSvs.getServerDataForUrl).toBeDefined();
AccountSvs.getServerDataForUrl().then(/*success callback*/function(){}, /*error callback*/function(){}, /*notify callback*/function(){});
    });

在spec中创建一个变量,该变量保存AccountService实例的引用,并使用angular inject函数将其实例化

现在,您可以使用jasmine间谍来测试功能,或者使用marchers来测试服务公共成员

    var AccountSvs = undefined;
    beforeEach(inject(function (AccountService) {
    AccountSvs = AccountService;
    }));

    it('..', function(){
      expect(AccountSvs.getServerDataForUrl).toBeDefined();
AccountSvs.getServerDataForUrl().then(/*success callback*/function(){}, /*error callback*/function(){}, /*notify callback*/function(){});
    });

在单元测试中处理promise并不是什么大问题,因为它是异步的,您需要执行以下操作

describe('AccountService',function(){
 var service = null;
    beforeEach(inject(function (AccountService) {
    service = AccountService;
    }));

    it('checkService here', function(done){
         expect(service .getServerDataForUrl).toBeDefined();
        service .getServerDataForUrl().then(function(resp){
         expect(resp.data).not.ToBeNull();   
          done();

     });
});

resp.data将包含从服务返回的实际数据。

在单元测试中处理promise并不是什么大问题,因为它是异步的,您需要执行以下操作

describe('AccountService',function(){
 var service = null;
    beforeEach(inject(function (AccountService) {
    service = AccountService;
    }));

    it('checkService here', function(done){
         expect(service .getServerDataForUrl).toBeDefined();
        service .getServerDataForUrl().then(function(resp){
         expect(resp.data).not.ToBeNull();   
          done();

     });
});

响应数据将包含从服务返回的实际数据。

您真的应该

return $http.get(url);
将承诺包装在延迟对象中没有意义

这是我能想到的唯一可测试的东西

describe('AccountService test', function() {
    var $http;

    beforeEach(module('accountModule', function($provide) {
        $provide.value('$http', $http = jasmine.createSpyObj('$http', ['get']));

        // if you aren't going to change the code to not wrap
        // the $http promise, add this

        var httpPromise = {
            success: function(cb) {
                cb('success');
                return httpPromise;
            },
            error: function(cb) {
                cb('error');
                return httpPromise;
            }
        };

        $http.get.and.returnValue(httpPromise);
    }));

    it('proxies through to $http.get', inject(AccountService) {
        AccountService.getServerDataForUrl('url');
        expect($http.get).toHaveBeenCalledWith('url');
    }));
});

你真的应该

return $http.get(url);
将承诺包装在延迟对象中没有意义

这是我能想到的唯一可测试的东西

describe('AccountService test', function() {
    var $http;

    beforeEach(module('accountModule', function($provide) {
        $provide.value('$http', $http = jasmine.createSpyObj('$http', ['get']));

        // if you aren't going to change the code to not wrap
        // the $http promise, add this

        var httpPromise = {
            success: function(cb) {
                cb('success');
                return httpPromise;
            },
            error: function(cb) {
                cb('error');
                return httpPromise;
            }
        };

        $http.get.and.returnValue(httpPromise);
    }));

    it('proxies through to $http.get', inject(AccountService) {
        AccountService.getServerDataForUrl('url');
        expect($http.get).toHaveBeenCalledWith('url');
    }));
});

这里唯一可以测试的是是否对特定url发出了请求。有很多在线测试http服务的例子。实际上,您在代码中所做的是多余的$http本身返回一个承诺。你为什么需要这样的代码?嗨,钱德尔马尼。这不是我的密码。我的任务是为它编写单元测试:这里唯一可以测试的是是否对特定url发出了请求。有很多在线测试http服务的例子。实际上,您在代码中所做的是多余的$http本身返回一个承诺。你为什么需要这样的代码?嗨,钱德尔马尼。这不是我的密码。我的任务是为它编写单元测试:我运行你的代码。但它得到消息:TypeError:无法读取未定义的属性“success”。我现在可以用你的代码做什么?@PhamMinhTan我以为你会更新代码,不把$http承诺封装在延迟对象中。我更新了我的答案太棒了!您的代码运行正常。谢谢。你能给我一些编写单元测试的教程和例子吗。因为,我想写。无论如何非常感谢。我运行您的代码。但它得到消息:TypeError:无法读取未定义的属性“success”。我现在可以用你的代码做什么?@PhamMinhTan我以为你会更新代码,不把$http承诺封装在延迟对象中。我更新了我的答案太棒了!您的代码运行正常。谢谢。你能给我一些编写单元测试的教程和例子吗。因为,我想写。无论如何非常感谢你。