Jasmine模拟的promise方法不会触发然后阻塞

时间:2016-11-03 22:06:33

标签: angularjs unit-testing jasmine karma-jasmine angular-mock

我无法获得一个模拟方法,该方法返回一个承诺,触发当时连接到它。

这是正在测试的服务。 get方法是它的重要方面。

angular.module('service.overtimeRules').factory('OvertimeRules', OvertimeRules);

function OvertimeRules(_, Message, OvertimeRulesModel) {
    const rules = [];

    return { get };

    function get() {
        return OvertimeRulesModel.get().then(
            data => {
                console.log('This never fires :(');
                rules.push(...data);
            },
            () => Message.add('Error retrieving the overtime rules.', 'danger')
        );
    }
}

这是spec文件。我得到的错误是TypeError: undefined is not an object (evaluating 'OvertimeRulesModel.get')。如果我删除了get describe包装器,则错误消失,但服务方法的then块仍然不会触发。

describe('OvertimeRules', () => {
    let $q, $rootScope, deferred, Message, OvertimeRules, OvertimeRulesModel;

    beforeEach(() => {
        module('globals');
        module('service.overtimeRules');
        module($provide => {
            $provide.value('Message', Message);
            $provide.value('OvertimeRulesModel', OvertimeRulesModel);
        });

        inject((_$q_, _$rootScope_, _OvertimeRules_) => {
            $q = _$q_;
            $rootScope = _$rootScope_;
            OvertimeRules = _OvertimeRules_;

            deferred = { OvertimeRulesModel: { get: $q.defer(), update: $q.defer } };

            Message = jasmine.createSpyObj('Message', ['add']);

            OvertimeRulesModel = jasmine.createSpyObj('OvertimeRulesModel', ['get']);
            OvertimeRulesModel.get.and.returnValue(deferred.OvertimeRulesModel.get.promise);
        });
    });

    describe('get', () => { // why would this cause an error?
        it('gets a list of rules and pushes them into the rules array', () => {
            deferred.OvertimeRulesModel.get.resolve(['rules']);
            OvertimeRules.get();
            $rootScope.$digest(); // $apply doesn't work either
            expect(OvertimeRules.rules).toEqual(['rules']);
        });
    });
});

可能重要的说明:

  • 只要代码简洁易读,我很乐意采用另一种方式。另外,我也需要拒绝承诺。
  • OvertimeRulesModel是此service.overtimeRules模块中的另一个工厂; Message是单独模块的一部分。
  • 我尝试将OvertimeRulesModel移动到自己的模块,但遇到了同样的错误。
  • 我正在使用 A = jasmine.createSpyObj(...); A.get.and.returnValue(promise); 控制器规范中的方法,一切正常。
  • 这些是单元测试,所以我宁愿避免注入实际的OvertimeRulesModel服务。

1 个答案:

答案 0 :(得分:0)

更好的回答

似乎我正在丢失提供给模块提供者的变量的引用。解决方案只是将createSpyObj调用移到$provide语句之上。

...
module('service.overtimeRules');

Message = jasmine.createSpyObj('Message', ['add']);
OvertimeRulesModel = jasmine.createSpyObj('OvertimeRulesModel', ['get']);

module($provide => {
    $provide.value('Message', Message);
    $provide.value('OvertimeRulesModel', OvertimeRulesModel);
});
...

使用解决方案修复了我遇到的另一个问题。此外,我不必更改returnValue语法。

旧答案:

显然,我需要做的就是将returnValue更改为callFake,如下所示:

OvertimeRulesModel = jasmine.createSpyObj('OvertimeRulesModel', ['get']);
OvertimeRulesModel.get.and.callFake(() => deferred.OvertimeRulesModel.get.promise);