AngularJS Jasmine spyOn:数字不是函数

时间:2014-04-10 06:50:06

标签: javascript angularjs testing jasmine karma-runner

我在运行使用模型进行服务调用的测试时遇到问题(从Web sql数据库中检索位置)。

这是控制器:

.controller(' LocationDetailCtrl',function($ scope,$ stateParams,LocationDbService,ProjectDbService){

    $scope.getLocation = function () {

        LocationDbService.get($stateParams.locationId,
            //Success
            function (tx, results) {

                console.log(JSON.stringify(results.rows.item(0)));

                if (results.rows.length > 0) {
                    console.log("We are in the if statement");
                    $scope.location = {
                        id: results.rows.item(0).id,
                        name: results.rows.item(0).name,
                        address: results.rows.item(0).address,
                        lat: results.rows.item(0).latitude,
                        lng: results.rows.item(0).longitude,
                        radius: results.rows.item(0).radius
                    }
                    $scope.$apply();
                }
            },
            //Error
            function () {
                console.log("Could not retrieve the location");
            })
    }

每次测试前:

var ctrl, scope, locationDbService, projectDbService, stateparams;
// inject the $controller and $rootScope services
// in the beforeEach block
beforeEach(angular.mock.inject(function ($controller, $rootScope, _LocationDbService_, _ProjectDbService_) {
    // Create a new scope that's a child of the $rootScope
    scope = $rootScope.$new();

    stateparams = {locationId: 1}; //mock your stateparams object with your id

    // Create the controller
    ctrl = $controller('LocationDetailCtrl', {
        $scope: scope,
        $stateParams: stateparams,
        LocationDbService: _LocationDbService_,
        ProjectDbService: _ProjectDbService_
    });
    locationDbService = _LocationDbService_;
    projectDbService = _ProjectDbService_;
}));

测试:

 it('a location should be retrieved',
    function () {
        spyOn(locationDbService, 'get').andCallFake(function(success, fail){

            var results = [];
            results.push(
                {
                    "id": 1,
                    "name": "Jeroen",
                    "address": "Kontitch",
                    "latitude": "27.6648274",
                    "longitude": "-81.51575350000002",
                    "radius": 50
                });

            var rs = {
                //rs is a SQLResultSetobject
                insertId: 0,
                rowsAffected: 0,
                rows: {
                    //rows is a SQLResultSetRowListobject
                    length: results.length,
                    item: function(index) {
                        return results[index];
                    }
                }
            };

            success(null, rs);
        });

        expect(scope.location).toBeUndefined();
        scope.getLocation();
        expect(scope.location).toBeDefined();
    });

我得到以下测试失败:

Number is not a function

有人知道我为什么会收到这个错误吗?提前谢谢!

3 个答案:

答案 0 :(得分:1)

我不相信你可以使用angular.mock.inject为你模拟自己的服务。我总是创建一个对象,其中包含所需的字段/函数,以通过间谍模拟服务。 注入你能做的:

inject(function ($controller, $rootScope)

嘲笑你不能

stateparams = {locationId: 1};
locationDbService = jasmine.createSpyObj('LocationDbService', ['method1', 'method2']);
projectDbService= jasmine.createSpyObj('ProjectDbService', ['method3', 'method4']);

然后使用以下命令创建控制器:

ctrl = $controller('LocationDetailCtrl', {
    $scope: scope,
    $stateParams: stateparams,
    LocationDbService: locationDbService ,
    ProjectDbService: projectDbService
});

通过这种方式,您可以完全控制注入控制器的内容,以便为单元测试真正隔离它。

答案 1 :(得分:0)

我在beforeEach中创建了以下模拟:

        locationDbServiceMock = {
        get: function (index,cbsuccess, cberror) {
            var results = [];
            results.push(
                {
                    "id": 1,
                    "name": "Jeroen",
                    "address": "Kontitch",
                    "latitude": "27.6648274",
                    "longitude": "-81.51575350000002",
                    "radius": 50
                });

            var rs = {
                //rs is a SQLResultSetobject
                insertId: 0,
                rowsAffected: 0,
                rows: {
                    //rows is a SQLResultSetRowListobject
                    length: results.length,
                    item: function (index) {
                        return results[index];
                    }
                }
            };

            cbsuccess(null, rs);
        }
    };

我只是将这个模拟的服务注入我的控制器,它可以工作。

答案 2 :(得分:0)

我发现我的代码出了什么问题,我忘记了索引参数:

你可以用这个:

function (locId, success, fail)

或者我在其他答案中的模型对象