编程语言
首页 > 编程语言> > javascript – 如何使用Jasmine测试AngularJS控制器在Promise中返回的值?

javascript – 如何使用Jasmine测试AngularJS控制器在Promise中返回的值?

作者:互联网

我有一个控制器,它暴露了一个在休息调用后返回一些文本的函数.它工作正常,但我无法使用Jasmine进行测试.测试中的promise处理程序内的代码永远不会执行.

控制器:

/* global Q */
'use strict';
angular.module('myModule', ['some.service'])
    .controller('MyCtrl', ['$scope', 'SomeSvc', function ($scope, SomeSvc) {

        $scope.getTheData = function (id) {
            var deferred = Q.defer();
            var processedResult = '';
            SomeSvc.getData(id)
                .then(function (result) {
                    //process data
                    processedResult = 'some stuff';
                    deferred.resolve(processedResult);
                })
                .fail(function (err) {
                    deferred.reject(err);
                });
            return deferred.promise;
        }
    }]);

考试:

describe('some tests', function() {
    var $scope;
    var $controller;
    var $httpBackend;
    beforeEach(function() {
        module('myModule');
        inject(function(_$rootScope_, _$controller_, _$httpBackend_) {
            $scope = _$rootScope_.$new();
            $controller = _$controller_;
            $httpBackend = _$httpBackend_;
            //mock the call that the SomeSvc call from the controller will make
            $httpBackend.expect('GET', 'the/url/to/my/data');
            $httpBackend.whenGET('the/url/to/my/data')
                .respond({data:'lots of data'});
            $controller ('MyCtrl', {
                $scope: $scope
            });
        });
    });

    describe('test the returned value from the promise', function() {
        var prom = $scope.getTheData(someId);
        prom.then(function(result) {
            expect(result).toBe('something expected');  //this code never runs
        })
    });
});

解决方法:

除非调用承诺回调,否则任何内部的任何内容都不会被运行 – 这就像你在这里遇到的假阳性风险一样.由于期望从未运行,测试将通过此处.

有很多方法可以确保你不会像这样得到误报.例子:

A)回报承诺

Jasmine将等待在超时内解决的承诺.

>如果未及时解决,测试将失败.
>如果承诺被拒绝,测试也将失败.

当心如果您忘记了回报,您的测试将给出误报!

describe('test the returned value from the promise', function() {
    return $scope.getTheData(someId)
    .then(function(result) {
        expect(result).toBe('something expected');
    });
});

B)使用Jasmine提供的完成回调测试方法

>如果在超时内未调用done,则测试将失败.
>如果使用参数调用done,则测试将失败.
这里的catch会将错误传递给jasmine,你会看到错误
在输出中.

注意如果您忘记了捕获,则会吞下您的错误并且您的测试将因通用超时错误而失败.

describe('test the returned value from the promise', function(done) {
    $scope.getTheData(someId)
    .then(function(result) {
        expect(result).toBe('something expected');
        done();
    })
    .catch(done);
});

C)使用间谍和手摇(同步测试)

如果你不完美,这可能是最安全的编写测试方法.

it('test the returned value from the promise', function() {
    var
      data = { data: 'lots of data' },
      successSpy = jasmine.createSpy('success'),
      failureSpy = jasmine.createSpy('failure');

    $scope.getTheData(someId).then(successSpy, failureSpy);

    $httpBackend.expect('GET', 'the/url/to/my/data').respond(200, data);
    $httpBackend.flush();

    expect(successSpy).toHaveBeenCalledWith(data);
    expect(failureSpy).not.toHaveBeenCalled();
});

同步测试技巧
您可以在需要时手动启动httpBackend,超时和更改范围,以使控制器/服务更进一步. $httpBackend.flush(),$timeout.flush(),scope.$apply().

标签:javascript,angularjs,promise,jasmine,q
来源: https://codeday.me/bug/20190717/1490396.html