在单元测试中模拟AngularJS服务的正确方法?

时间:2013-11-03 06:30:15

标签: unit-testing angularjs jasmine

我有以下控制器和服务,我试图在Jasmine中编写测试。我对此很陌生,只是想看看我是否采用了正确的方法来测试和模拟我的服务。

控制器

(function () {
    'use strict';

    var app = angular.module('cs');

    app.controller('PlateCheckCtrl', ['$scope', 'PlateCheckService', function ($scope, PlateCheckService) {
        var plateCheck = {
            plateNumber: '',
            message: '',
            alertClass: '',
            checkPlate: function (plateNumber) {
                var _this = this;

                PlateCheckService.checkPlate(plateNumber).then(function (response) {
                    _this.message = response.message;
                    _this.alertClass = response.alertClass;
                });
            }
        };

        $scope.plateCheck = plateCheck;
    }]);

}());

服务

(function () {
    'use strict';

    var app = angular.module('cs');

    app.service('PlateCheckService', ['$http', function ($http) {
        return {
            checkPlate: function (plateNumber) {
                return $http.post('PlateCheck/Index', {
                    plateNumber: plateNumber
                }).then(function (response) {
                    return {
                        message: response.data.VehicleAtl === null ? 'Clean' : 'Hot',
                        alertClass: response.data.VehicleAtl === null ? 'alert-success' : 'alert-danger'
                    };
                });
            }
        };
    }]);

}());

控制器测试

describe('Spec Template', function () {
    var scope,
        controller;

    beforeEach(function () {
        module('cs');

        inject(function ($rootScope, $controller, $q) {
            scope = $rootScope.$new();

            controller = $controller('PlateCheckCtrl', {
                $scope: scope, PlateCheckService: {
                    checkPlate: function (plateNumber) {
                        var d = $q.defer();

                        if (plateNumber === '123') {
                            d.resolve({
                                message: 'Clean',
                                alertClass: 'alert-success'
                            })
                        } else {
                            d.resolve({
                                message: 'Hot',
                                alertClass: 'alert-danger'
                            })
                        }

                        return d.promise;
                    }
                }
            });
        });
    });

    it('Should return "Clean" result', function () {
        scope.plateCheck.checkPlate('123');
        scope.$apply();
        expect(scope.plateCheck.message).toBe('Clean');
        expect(scope.plateCheck.alertClass).toBe('alert-success');
    });

    it('Should return "Hot" result', function () {
        scope.plateCheck.checkPlate('123456');
        scope.$apply();
        expect(scope.plateCheck.message).toBe('Hot');
        expect(scope.plateCheck.alertClass).toBe('alert-danger');
    });

});

服务测试

describe('Plate Check Service', function () {
    var httpBackend,
        service;

    beforeEach(function () {
        module('cs');

        inject(function ($httpBackend, PlateCheckService) {
            httpBackend = $httpBackend;
            httpBackend.whenPOST('PlateCheck/Index', { plateNumber: '123' }).respond({ VehicleAtl: null });
            httpBackend.whenPOST('PlateCheck/Index', { plateNumber: '123456' }).respond({ VehicleAtl: {} });
            service = PlateCheckService;
        });
    });

    afterEach(function () {
        httpBackend.verifyNoOutstandingExpectation();
        httpBackend.verifyNoOutstandingRequest();
    });

    it('Should send the request to the server', function () {
        httpBackend.expectPOST('PlateCheck/Index', { plateNumber: '123' });
        service.checkPlate('123');
        httpBackend.flush();
    });

    it('Should return a "Clean" result', function () {
        var result;

        service.checkPlate('123').then(function (response) {
            result = response;
        });

        httpBackend.flush();

        expect(result.message).toBe('Clean');
        expect(result.alertClass).toBe('alert-success');
    });

    it('Should return a "Hot" result', function () {
        var result;

        service.checkPlate('123456').then(function (response) {
            result = response;
        });

        httpBackend.flush();

        expect(result.message).toBe('Hot');
        expect(result.alertClass).toBe('alert-danger');
    });
});

1 个答案:

答案 0 :(得分:1)

您的控制器实际上并不具有该服务所具有的任何功能。所以你不应该在控制器中测试服务功能。

describe('Spec Template', function () {
var scope,
    controller,
    PlateCheckServiceMock = {
         checkPlate: function () {}
    };  


beforeEach(function () {
    module('cs');

    inject(function ($rootScope, $controller, $q) {
        scope = $rootScope.$new();
        spyOn(PlateCheckService, 'checkPlate').andCallThrough();
        controller = $controller('PlateCheckCtrl', {
            $scope: scope, 
            PlateCheckService: PlateCheckServiceMock
          }
        });
    });
});