使用Kendo Grid/Datasource的单元测试Angular Controller

Unit testing Angular Controller that uses Kendo Grid/Datasource

本文关键字:单元测试 Angular Controller Datasource Kendo Grid 使用      更新时间:2023-09-26

我的项目使用AngularJS+Kendo UI。我正在尝试测试我的一个使用剑道UI网格的控制器:

angular.module('myApp')('DevicesCtrl', function ($scope) {
    $scope.gridOptions = {
        dataSource: {
            transport: {
                read: {
                    url: "/devices",
                    dataType: "json"
                }
            },
            change: function(){
                var view = this.view();
                $scope.devices = [];
                $.each(view, function(i, v) {
                    $scope.devices.push({id: v.id, description: v.name, status: v.status  == 0 ? "failure" : "success"});
                });
                $scope.$apply();
            }
        },
        columns: [
            {
                field: "name",
                title: "Name",
                width: 250,
                template: function (item) {
                    var itemStatus = item.status == 0 ? 'failure' : 'success';
                    return '<div label size="small" operation="' + itemStatus + '" label="' + item.name + '"></div>';
                }
            },
            {
                field: "status",
                title: "Status"
            }
        ]
    };
});

当我编写单元测试时,我预计会调用一个GET请求:

describe('deviceCtrl', function () {
    var scope, deviceCtrl, httpBackend, timeout;
    beforeEach(module("myApp"));
    beforeEach(module('src/modules/devices/views/device.html'));
    beforeEach(inject(function ($controller, $rootScope, $httpBackend, $timeout, $state) {
        scope = $rootScope.$new();
        httpBackend = $httpBackend;
        timeout = $timeout;
        httpBackend.expectGET('languages/en_US.json').respond({});
        deviceCtrl = $controller("DeviceCtrl", {
            $scope: scope
        });
        $state.go("devices");
        timeout.flush()
    }));
    it('should load the switch list', function () {
        httpBackend.expectGET("/devices").respond(
            [{"id":"1","name":"name 1","status":"1"},
            {"id":"2","name":"name 2","status":"2"}]
        );
        httpBackend.flush();
    });
});

但这种期望从未得到满足,也没有提出任何要求。所以我的问题是:有没有办法让Kendo Grid/Datasource进行这个调用,这样我就可以嘲笑它了?

我看到了一些关于如何使用Mockjax的示例(http://www.telerik.com/forums/best-practice-mocking-with-datasource)但我更喜欢使用角度库来做到这一点。

经过大量研究,我可以找到一些方法来测试使用Kendo数据源的控制器。

Kendo有自己的方法来调用Ajax来获取数据,并且不使用常规的Angular$http来实现这一点,所以使用Angular工具(Angular mock)进行测试有点棘手。让我们进入选项:

1–使用常规的Angular方式进行Ajax调用

Kendo让我们改变它获取数据的方式,所以不用这么做:

dataSource: new kendo.data.DataSource({
            transport: {
                read: {
                    url: "/devices,
                    dataType: "json"
                }
            },
            change: function(){
                var view = this.view();
                $scope.devices = [];
                $.each(view, function(i, v) {
                    $scope.devices.push({id: v.id, description: v.name, status: v.status  == 0 ? "failure" : "success"});
                });
                $scope.$apply();
            }
        });

我们将改为:

dataSource: new kendo.data.DataSource({
            transport: {
                read: function(options){
                    $http.get("/devices").then(function(response){
                        options.success(response.data);
                        $scope.devices = [];
                        response.data.forEach(function(v){
                            $scope.devices.push({id: v.id, description: v.name, status: v.status  == 0 ? "failure" : "success"});
                        });
                    });
                }
            }
        });

然后我们可以使用常规的$httpBackend.expectGET(url)来模拟Ajax调用。我个人喜欢这种方法,因为我们有更多的控制权。Ps.:使用函数内部的变量"options",我们可以访问Grid过滤器、排序和分页值。

2–模仿剑道Ajax呼叫

通过这种方式,我们在Controller上几乎没有任何更改,唯一需要更改的是使用新的kendo.data.Datasource({})创建一个新的数据源,而不仅仅是传递选项。这是需要的,因为我们在测试用例中调用了read函数。我尝试了不同的方法来模拟这个Ajax请求,但唯一能让它工作的方法是使用一个名为Jasmine Ajax的工具。在测试用例中,我们会写一些类似的东西:

var request = jasmine.Ajax.requests.mostRecent();
request.response(MockData);

我希望这能帮助其他人。