单元使用Jasmine测试大量注入的服务

时间:2016-01-07 07:35:55

标签: angularjs unit-testing jasmine

我对使用Jasmine的AngularJs单元测试非常陌生。所以你能告诉我如何使用Jasmine.Thanks提前测试下面提到的控制器和countyService.getAllCountiesAsync()方法。

注意:下面的控制器有超过50个注入服务(我在下面显示了几个)。所以我不知道哪种方法对于模拟那些也有好处?

控制器:

(function () {
    appModule.controller('myController', [
        '$scope', '$modalInstance', 'abp.services.app.property', 'abp.services.app.county', 'abp.services.app.propertyClass', 'abp.services.app.schoolDistrict'
        function ($scope, $modalInstance, propertyService, countyService, propertyClassService, schoolDistrictService) {

   vm.getAllCounties = function () {
                countyService.getAllCountiesAsync().success(function (result) {
                    vm.counties = result.items;
                });
            };

            vm.getAllCounties();

} ]);
})();

WebApi方法:

  public async Task<ListResultOutput<CountyListDto>> GetAllCountiesAsync()
        {
            var counties = await _countyRepository
                .GetAllListAsync();

            return new ListResultOutput<CountyListDto>(counties.OrderBy(o => o.Name).MapTo<List<CountyListDto>>());
        }

2 个答案:

答案 0 :(得分:2)

您应该为服务和控制器编写测试用例。

对于服务'Daan van Hulst'已经给出了答案,对于控制器,请参见下面的代码:

describe('service tests', function () {

var $compile,$controller,myController, $rootScope, propertyService, countyService, propertyClassService, schoolDistrictService;
//All module dependencies   
beforeEach(module('your-app-name'));

//inject required services and _$controller_ to create controller
beforeEach(inject(function(_$compile_,_$controller_, _$rootScope_, _propertyService_, _countyService_, _propertyClassService_, _schoolDistrictService_) {

$compile = _$compile_;
        $rootScope = _$rootScope_;
$controller = _$controller_; // This is IMP
    countyService = _countyService_;
    // remianig services
    // Now create controller 
    myController = $controller('myController', {
                $scope : scope,
                propertyService : propertyService // all other services
    });}

it('should test something', function() {
    spyOn(countyService, 'getAllCountiesAsync').and.callFake(function () {
                var d = q.defer();
                d.resolve({ items: [{data:'somedata'}] });
                return d.promise;
            });     
    myController.getAllCounties();

    expect(myController.counties).not.toBe(null);

});

<强>更新

我可能犯了错误,但这就是这个想法:

describe('service tests', function () {

var $compile, $rootScope, scope, vm, propertyService, countyService, propertyClassService, schoolDistrictService;
  beforeEach(module('your-app-name'));
  beforeEach(inject(function(_$compile_, _$rootScope_, $controller, _propertyService_, _countyService_, _propertyClassService_, _schoolDistrictService_) {
    $compile = _$compile_;
    $rootScope = _$rootScope_;
    scope = $rootScope.$new();
    propertyService = _propertyService_;
    countyService = _countyService_;
    propertyClassService = _propertyClassService_;
    schoolDistrictService = _schoolDistrictService_;

    vm = $controller('myController', {'$scope': scope})

    spyOn(countyService, "getAllCountiesAsync").and.callFake(function() {
        var deferred = $q.defer();
        deferred.resolve({data: [{id:0}]});
        return deferred.promise;
    });
  }));

  it('can do remote call', inject(function() {

    //Arrange
    result = [{id:0}];

    // Act
    vm.getAllCounties();

    // Assert
    expect(vm.counties).toBe(result); //assert to whatever is resolved in the spyOn function

  });   

});
}

答案 1 :(得分:1)

我假设您为所有服务创建了Angular服务,并且您的应用正在运行。然后,您可以在测试中注入它们:

describe('service tests', function () {

var $compile, $rootScope, scope, vm, propertyService, countyService, propertyClassService, schoolDistrictService;
  beforeEach(module('your-app-name'));
  beforeEach(inject(function(_$compile_, _$rootScope_, $controller, _propertyService_, _countyService_, _propertyClassService_, _schoolDistrictService_) {
    $compile = _$compile_;
    $rootScope = _$rootScope_;
    scope = $rootScope.$new();
    propertyService = _propertyService_;
    countyService = _countyService_;
    propertyClassService = _propertyClassService_;
    schoolDistrictService = _schoolDistrictService_;

    // Create the controller, and pass in the scope with possible variables that you want to mock.
    vm = $controller('myController', {'$scope': scope})

    //Create a spy on your getAllCountiesAsync function and make it return a mock promise with mock data.
    spyOn(countyService, "getAllCountiesAsync").and.callFake(function() {
        var deferred = $q.defer();
        deferred.resolve({data: [{id:0}]});
        return deferred.promise;
    });
  }));

  it('can do remote call', inject(function() {

    //Arrange
    result = [{id:0}];

    // Act
    vm.getAllCounties();

    //I think that you also have to do this, but I am not a 100% sure.
    scope.$apply();

    // Assert
    expect(vm.counties).toBe(result); //assert to whatever is resolved in the spyOn function

  });   

});
}

<强>更新

我在上面的答案中意外地发布了我的解决方案,所以现在纠正了它。您可以使用$ controller创建控制器并传入范围对象。您还可以传入任何其他依赖项。然后在服务上创建一个间谍,一旦调用它,调用一个不同的函数,用一个模拟数据解析一个promise:

{{1}}