【问题标题】:jasmine test case for Restangular within a function函数中 Restangular 的茉莉花测试用例
【发布时间】:2014-11-20 09:58:06
【问题描述】:

如何为如下所示的场景编写 Rectangular 的 jasmine 测试

脚本

$scope.allEmployees = [{
            visible: true,
            empId: "EMP148"
 }];

$scope.employeeDocuments = {  "EMP148": [{
                                        "empId": "EMP148",
                                        "department": "Sales",
                                        "firstName": "Manu",
                                        "lastName": "Mathew",
                                        "place": "Kolkata"
                                        }]
                           };

var employeesCopy = angular.copy($scope.allEmployees);
$scope.allEmployees.push({visible: true, empId: "EMP489"});  

$scope.addEmployees = function (employeesCopy) {
    var newEmployee = {visible: true, empId: "EMP489"};
    var emplyeeList = {
        employees: $scope.allEmployees,
        newEmployee: newEmployee
    };
    Restangular.all('emp/getEmployees').post(emplyeeList).then(function (employees) {
        if (!_.isEmpty(employees[emplyeeList.newEmployee.empId])) {
            if ($scope.employeeDocuments.hasOwnProperty(emplyeeList.newEmployee.empId)) {
                delete $scope.employeeDocuments[emplyeeList.newEmployee.empId];
            }
            $scope.employeeDocuments[emplyeeList.newEmployee.empId] = employees[emplyeeList.newEmployee.empId];
            setMyEmployees(true);
            $scope.flag = true;
            console.log("success");
        } else {
            $scope.employeeDocuments = employeesCopy;
            console.log("no documents");
        }
        $scope.flag = false;
    }, function (error) {
        console.log("failed");
        $scope.flag = false;
    });
};

$scope.addEmployees(employeesCopy);
setMyEmployees = function (flag)
{
    // other implementation
};

我写了一个如下所示的测试用例,但我得到了像spyOn could not find an object to spy upon for all()这样的异常

测试用例

WORKING DEMO - 包含完整的逻辑和测试用例

describe('Testing Controllers', function() {
    describe('Testing EmployeeController Controller', function() {
        var EmployeeController, $scope, $httpBackend, Restangular;

        beforeEach(function() {
           module('emp');
        }); 

        beforeEach(inject(function($controller, $rootScope, $filter, $injector, Restangular, $httpBackend) {
            $scope = $rootScope.$new();
            $httpBackend = $httpBackend;
            Restangular = $injector.get("Restangular");
            EmployeeController = $controller('EmployeeController ', {
                $rootScope: $rootScope,
                $scope: $scope,
                $filter: $filter
            });
        }));

        it('should add new employees when addEmployees() is called', inject(function($httpBackend)
        {
           $scope.allEmployees = [{
                                    visible: true,
                                    empId: "EMP148"
                              }];

           $scope.employeeDocuments = {  "EMP148": [{
                                            "empId": "EMP148",
                                            "department": "Sales",
                                            "firstName": "Manu",
                                            "lastName": "Mathew",
                                            "place": "Kolkata"
                                            }]
                                   };

           var employeesCopy = angular.copy($scope.allEmployees);

           spyOn(Restangular, 'all').andCallThrough();

           var newEmployee = {visible: true, empId: "EMP489"};
           var emplyeeList = {
                employees: $scope.allEmployees,
                newEmployee: newEmployee
           };

           var mockToReturn = {
                "EMP489": [{
                "empId": "EMP489",
                "department": "Sales",
                "firstName": "Ram",
                "lastName": "Mohan",
                "place": "Delhi"
                }]
            };
            $scope.addEmployees(employeesCopy);
            $httpBackend.expectPOST('emp/getEmployees',emplyeeList).respond(mockToReturn);
            expect(Restangular.all).toHaveBeenCalledWith('emp/getEmployees');
            expect(setMyEmployees(true)).toHaveBeenCalled();

        }));
    });
});

【问题讨论】:

    标签: javascript angularjs unit-testing jasmine restangular


    【解决方案1】:

    你有倍数问题:

    首先,要回答您使用 toHavebeenCalled 的问题,您必须先创建一个间谍。

    我要做的是将 setMyEmployees 放在作用域级别,然后在作用域上添加一个间谍

    spyOn($scope);
    

    但是您有一个发出异步请求的测试,因此您的测试用例将失败,因为它会在异步请求成功之前到达末尾。

    使用 jasmine 2,您可以使用 done() 进行异步测试:

    it('should add new employees when addEmployees() is called', function(done) 
    {
        //call when asyncronous operation is finish
        done();
    }
    

    但是以您创建函数的方式,您不能使用 done。 你的方法或承诺中必须有一个回调块

    回调:

    $scope.addEmployees = function(employeesCopy, success, failure)
    {
        //code
        Restangular.all('user/getEmployees').post(emplyeeList).then(function(employees)
        {
            if (!_.isEmpty(employees[emplyeeList.employeeId]))
            {
               // code
            }
            else
            {
                // code
            }
            success();
            $scope.flag = false;
        }, function(error)
        {
            failure();
            $scope.flag = false;
        });
    };
    

    注意 toHaveBeenCall 语法

    it('should add new employees when addEmployees() is called', function(done) 
    {
    var employeesCopy = {
        firstName: "Manu",
        lastName: "Sam"
    };
    
    spyOn($scope);
    
    $scope.addEmployees(employeesCopy, function(){
    
        done();
    
    });
    
    expect($scope.setMyEmployees).toHaveBeenCalledWith(true);
    });
    

    我更喜欢 Promise 语法:

    $scope.addEmployees = function(employeesCopy, defer)
    {
        //code
        Restangular.all('user/getEmployees').post(emplyeeList).then(function(employees)
        {
            if (!_.isEmpty(employees[emplyeeList.employeeId]))
            {
               // code
            }
            else
            {
                // code
            }
            defer.resolve();
            $scope.flag = false;
        }, function(error)
        {
            defer.reject();
            $scope.flag = false;
        });
    };
    
    
    it('should add new employees when addEmployees() is called', function(done) 
    {
    var employeesCopy = {
        firstName: "Manu",
        lastName: "Sam"
    };
    
    spyOn($scope);
    
    var defer = $q.defer;
    defer.promise.then(function(){
    
        console.log("success");
        done();
    }, function (){
        done();
        console.log("error");
    });
    
    $scope.addEmployees(employeesCopy, defer);
    
    expect($scope.setMyEmployees).toHaveBeenCalledWith(true);
    });
    

    如果您希望您的测试真正统一,您将遇到的最后一个问题是模拟网络调用(否则您还要测试后端答案,这可能是您想要的) 如果您想模拟通话,您应该查看 $httpBackend,这篇博文似乎有更多信息:https://ath3nd.wordpress.com/2013/08/05/15/(不是我的)

    编辑,添加依赖来测试,在你的 it() 之前,使用 beforeEach :

    var myService, Restangular;
        beforeEach(function() {
            inject(function($injector) {
                myService = $injector.get('MyService');//exemple service
                Restangular = $injector.get("Restangular");
            });
        });
    

    编辑 2:

    好吧,我解释的不正确,试试:

    beforeEach(inject(function($controller, $rootScope, $filter, $injector, _Restangular_, _$httpBackend_) {
            $scope = $rootScope.$new();
            $httpBackend = _$httpBackend_;
            Restangular = _Restangular_;
            EmployeeController = $controller('EmployeeController ', {
                $rootScope: $rootScope,
                $scope: $scope,
                $filter: $filter
            });
        }));
    

    【讨论】:

    • 实际上我需要在测试用例中模拟和显示restangular的东西
    • 我已经用你提供的东西更新了我的答案,但现在得到<failure type="">Error: spyOn could not find an object to spy upon for all()
    • 尝试在您的注入中添加 Restangular ?
    • 现在我收到<failure type="">TypeError: 'undefined' is not a function (evaluating 'spyOn(Restangular,'all').andCallThrough()')
    • 有些东西是未定义的,可能是 Restangular,我将在我的帖子中添加一个编辑来展示如何添加依赖关系
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-03-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-09-04
    • 1970-01-01
    相关资源
    最近更新 更多