javascript - 如何测试调用 AJAX 函数而不使用 jasmine 触发它的函数?

标签 javascript jquery angularjs unit-testing karma-jasmine-ajax

我已 checkin How do I verify jQuery AJAX events with Jasmine?How to test an Angular controller with a function that makes an AJAX call without mocking the AJAX call?但由于某种原因,他们不一定会推出适合我的格式。

我的问题是我正在对一个函数进行单元测试,该函数调用触发 AJAX 请求的函数。我想在不触发 AJAX 请求(或停止该请求)的情况下测试外部函数,这样我就不会在数据服务器中收到一堆错误的数据。

这是我的外部函数(它调用包含 AJAX 的函数):

vm.clickSubmit = function () {
    vm.loading = true; // starts the loading spinner
    vm.updateData(); // makes current data current in the data model
    vm.inputData = {    // build the data to be submitted
        ...
    };
    vm.submit(); // calls the AJAX function
};

这是我的 AJAX 函数:

vm.submit = function () {
    var d = $.ajax({
        type: "POST"
        , data: angular.toJson(vm.inputData)
        , url: "http://submit_the_data"
        , contentType: "application/json"
        , xhrFields: { withCredentials: true }
        , crossDomain: true
    })
    .success(function (resp) {
        DataService.ticketNumber = resp; // returns ticket# for the data model
    })
    .error(function (error) {
        DataService.ticketNumber = DataService.submitError;
    });
    d.then(function (d) {
        vm.loading = false; // stops the loading spinner
        DataService.tickets = []; // empty's the array to be filled anew
        $location.path('/submitted'); // success splash html
        $scope.$apply();
    });
};

我已经编写了所有将读取和验证 inputData 对象中的值的测试,但我不确定如何包围对 clickSubmit() 的调用> 因此实际上没有任何内容提交到服务器。我已经在单元测试中达到了这一点:

'use strict';

describe('Controller: HomeController', function () {
    beforeEach(module('tickets'));
    var controller, scope, $location, DataService;
    var tests = 0;
    beforeEach(inject(function ($rootScope, $controller, _$location_, _DataService_) {
        $location = _$location_;
        DataService = _DataService_;
        scope = $rootScope.$new();
        controller = $controller('HomeController', {
            $scope: scope
        });
    }));
    afterEach(function () {
        tests += 1;
    });
    describe('clickSubmit should verify data and submit new ticket', function () {
        beforeEach(function () {
            jasmine.Ajax.install();
            controller.loading = false;
                ... // inputData fields filled in with test data
        });
        afterEach(function () {
            jasmine.Ajax.uninstall();
        });
        it('should start the spinner when called', function () {
            controller.clickSubmit();
            expect(controller.loading).toBeTruthy();
        });
        // other it('') tests
    });
    it('should have tests', function () {
        expect(tests).toBeGreaterThan(0);
    });
});

那么在加载微调器上的期望之后应该做什么来取消实际代码中对 vm.submit() 的调用?

谢谢

-C§

最佳答案

我建议模拟该调用而不是实际调用它。粒度由您决定,您可以 stub ajax 调用,也可以 stub 整个提交函数。

以下是如何 stub 提交函数:

spyOn(controller, 'submit').and.callFake(function() {
    DataService.ticketNumber = somevalue;
});

将该代码放置在实际调用 Controller (caller.clickSubmit())之前。

然后您可以跟进对 spy 的期望,例如:

expect(controller.submit).toHaveBeenCalled()

或与 spy 相关的任何其他期望。

这里是 Jasmine 文档:http://jasmine.github.io/2.0/introduction.html
向下看“ spy ”区域。

如果你想模拟 ajax 调用,你必须模拟这样的 promise :

spyOn($, 'ajax').and.callFake(function() {
    var deferred = $q.defer();
    deferred.resolve(someResponse);
    return deferred.promise;
});

此外,为了让代码等待 Promise 解析,在进行提交调用后,您需要运行 $scope.$digest() 以便 Angular 可以处理 Promise 解析。然后,您可以根据 promise 的解决或拒绝来检查您对代码的期望。

关于javascript - 如何测试调用 AJAX 函数而不使用 jasmine 触发它的函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31975928/

相关文章:

Javascript定时器切换功能

javascript - 使用 requireJS 加载 IE 依赖

javascript - ajax php javascript 集成不起作用

javascript - 尝试根据用户输入、JS/JQuery 从数组中检索数据

javascript - 如何防止 ng-repeat 中出现重复的 Angular 键?

angularjs - 在同一范围内查找具有相同指令的其他元素?

javascript - Angular (jquery timepicker)无法获取输入值

javascript - Google pubads 出现然后消失

javascript - 用于阻止页面在新选项卡中打开的 HTML 代码

jquery - 导航之外没有可点击的内容(hrefs 或点击功能)