【问题标题】:How do I test a rejected Angular (1.6.1) promise in jasmine?如何在茉莉花中测试被拒绝的 Angular (1.6.1) 承诺?
【发布时间】:2017-06-02 05:30:20
【问题描述】:

以下是我在 Angular 1.5.x 中测试被拒绝的 Promise 的方法。更新到 1.6.1 引入了“可能未处理的拒绝”错误。我了解此错误的目的,但我还没有找到解决它的简单方法。 Jasmine (2.5.x) 的 and.throwError() 方法似乎由于错误而导致测试失败。

describe('TestTarget', () => {
    let $q, $rootScope, TestTarget, SomeModel;

    beforeEach(() => {
        SomeModel = jasmine.createSpyObj('SomeModel', ['get']);

        module('something');
        module($provide => {
            $provide.value('SomeModel', SomeModel);
        });

        inject((_$q_, _$rootScope_, _TestTarget_) => {
            $q = _$q_;
            $rootScope = _$rootScope_;
            TestTarget = _TestTarget_;
        });
    });

    describe('get()', () => {
        it('on error, adds a danger message', () => {
            SomeModel.get.and.returnValue($q.reject());
            // SomeModel.get.and.throwError(); // doesn't work either
            TestTarget.get();
            $rootScope.$digest();
            expect(SomeModel.get).toHaveBeenCalled();
            expect(<< the rejection outcome of TestTarget.get().then() >>);
        });
    });
});

我想继续在我的模型、服务和控制器中传递被拒绝的 Promise。

【问题讨论】:

  • 这真的取决于您如何实现TestTarget.get,但请阅读我的答案作为示例,对它做出一些假设

标签: angularjs jasmine promise q


【解决方案1】:

我在 Angular 1.6.1 中遇到了这个问题。在您的测试中尝试使用 callFake 而不是 returnValue。

describe('TestTarget', () => {
let $q, $rootScope, TestTarget, SomeModel;

beforeEach(() => {
    SomeModel = jasmine.createSpyObj('SomeModel', ['get']);

    module('something');
    module($provide => {
        $provide.value('SomeModel', SomeModel);
    });

    inject((_$q_, _$rootScope_, _TestTarget_) => {
        $q = _$q_;
        $rootScope = _$rootScope_;
        TestTarget = _TestTarget_;
    });
});

describe('get()', () => {
    it('on error, adds a danger message', () => {
        SomeModel.get.and.callFake(() => $q.reject());
        // SomeModel.get.and.throwError(); // doesn't work either
        TestTarget.get();
        $rootScope.$digest();
        expect(SomeModel.get).toHaveBeenCalled();
        expect(<< the rejection outcome of TestTarget.get().then() >>);
    });
});

});

【讨论】:

    【解决方案2】:

    假设你的实际代码是这样的:

    angular.module('myApp').service('TestTarget', ['SomeModel', function(SomeModel) {
        this.get = function() {
            return SomeModel.get();
        }
    }]);
    

    我的假设是您没有链接到返回的 Promise 的 .catch 块。 在这种情况下,您可以像这样简单地测试它:

    it('on error, adds a danger message', () => {
        SomeModel.get.and.returnValue($q.reject('some error'));
        TestTarget.get()
            .then(function() {
                fail('the promise should not have been resolved');
            }).catch(function(err) {
                expect(err).toBe('some error');
            });
        $rootScope.$digest();
        expect(SomeModel.get).toHaveBeenCalled();
    });
    

    请注意,我在函数调用中添加了一个 catch 块。 $rootScope.$digest() 确保 promise 得到解决,并且所有链接的 thencatch 块都被调用。

    【讨论】:

    • 这按预期工作,但它背后的原因是什么?有人吗??因为,根据 Jasmine 文档,returnValue 和 callFake 应该是相同的......
    • 区别不在于使用callFakereturnValue。我猜这是由于将期望置于保证异步然后阻塞,而不是同步阻塞(并希望 Angular 能够解决异步顺序)。
    猜你喜欢
    • 2023-03-27
    • 1970-01-01
    • 2021-05-25
    • 1970-01-01
    • 1970-01-01
    • 2016-04-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多