angularjs单元测试无法注入服务

时间:2018-03-15 10:39:35

标签: angularjs jasmine karma-jasmine

我的服务非常简单:

'use strict';

angular.module('sapphire.orders').service('deliveryDatesService', service);

function service() {
    return {
        clearAddressReason: clearAddressReason,
        getMinDate: getMinDate
    };

    //////////////////////////////////////////////////

    function clearAddressReason(model, dateReasons, reasons) {
        if (model.manualAddress) {
            model.overrideDates = true;
            reasons.date = dateReasons.filter(function (item) {
                return item.value === 'D4';
            })[0];
        } else {
            reasons.address = null;
            if (!reasons.date || reasons.date.value === 'D4') {
                reasons.date = null;
                model.overrideDates = false;
            }
        }
    };

    function getMinDate(model) {
        var now = new Date();

        // If we are not overriding dates, set to today
        if (!model.overrideDates) return now;

        // If dates are overriden, then the min date is today + daysToDispatch
        return new Date(now.setDate(now.getDate() + model.daysToDispatch));
    };
};

它没有依赖关系,所以我想测试方法。 所以我试图创建一个这样的规范:

'use strict';

describe('Service: deliveryDatesService', function () {
    beforeEach(module('sapphire.orders'));

    var service,
        reasons,
        dateReasons;

    beforeEach(inject(function (deliveryDatesService) {
        console.log(deliveryDatesService);
        service = deliveryDatesService;
        reasons = {};
        dateReasons = [{ value: 'D4' }];
    }));

    it('can create an instance of the service', function () {
        expect(service).toBeDefined();
    });

    it('if manual delivery address is true, then override dates should be true', function () {
        var model = { manualDeliveryDate: true };
        service.clearAddressReason(model, dateReasons, reasons);
        expect(model.overrideDates).toBe(true);
    });

    it('if manual delivery address is false, then override dates should be false', function () {
        var model = { manualDeliveryDate: false };
        service.clearAddressReason(model, dateReasons, reasons);
        expect(model.overrideDates).toBe(false);
    });

    it('minimum date cannot be less than today', function () {
        var model = { };
        var minDate = service.getMinDate(model);
        var now = new Date();
        expect(minDate).toBeGreaterThan(now);
    });
});

但我的服务总是未定义的。有人可以告诉我,我做错了吗?

更新

因此,事实证明这与一个或多个以某种方式干扰的服务有关。 在我的 karma.conf.js 中,我已经宣布了所有的bower应用程序,然后是:

'src/app/app.module.js',
'src/app/**/*module.js',
'src/app/**/*constants.js',
'src/app/**/*service.js',
'src/app/**/*routes.js',
'src/app/**/*.js',
'test/spec/**/*.js'

我在我的脚本目录的根目录中创建了一个测试服务,然后创建了一个spec文件以查看它是否已创建。它向我呻吟着一个完全没有关系的文件中的引用错误。它对这段代码抱怨不已:

angular.module('sapphire.core').factory('options', service);

function service($rootScope) {
    return {
        get: get,
        save: save
    };

    //////////////////////////////////////////////////

    function get() {
        if (Modernizr.localstorage) {
            var storageData = angular.fromJson(localStorage.options);
            if (storageData) {
                return angular.fromJson(storageData);
            }
        }

        return {
            background: {
                enabled: true,
                enableSnow: true,
                opacity: 0.6
            }
        };
    };

    function save(options) {
        if (Modernizr.localstorage) {
            localStorage.options = angular.toJson(options);
            $rootScope.$options = get();
        }
    };
};

声明Modernizr未定义。 我将代码更改为:

angular.module('sapphire.core').factory('options', service);

function service($rootScope) {
    return {
        get: get,
        save: save
    };

    //////////////////////////////////////////////////

    function get() {
        if (typeof Modernizr == 'object' && Modernizr.localstorage) {
            var storageData = angular.fromJson(localStorage.options);
            if (storageData) {
                return angular.fromJson(storageData);
            }
        }

        return {
            background: {
                enabled: true,
                enableSnow: true,
                opacity: 0.6
            }
        };
    };

    function save(options) {
        if (typeof Modernizr == 'object' && Modernizr.localstorage) {
            localStorage.options = angular.toJson(options);
            $rootScope.$options = get();
        }
    };
};

它开始工作了。但我的另一个测试不是。 所以我将 karma.conf.js 中的引用更改为:

'src/app/app.module.js',
'src/app/orders/orders.module.js',
'src/app/orders/shared/*.js',
'test/spec/**/*.js'

它开始工作了。 这让我相信我的应用程序在某处出现了问题。也许像 Modernizr 这样的另一个参考。我仍然有一个悬而未决的问题。不依赖于其他服务的服务如何干扰? 我认为值得注意的是,每个服务,控制器,指令都在它自己的文件中,并且它们都遵循这种结构:

(function () {
    'use strict';

    angular.module('sapphire.core').factory('options', service);

    function service($rootScope) {
        return {
            get: get,
            save: save
        };

        //////////////////////////////////////////////////

        function get() {
            if (typeof Modernizr == 'object' && Modernizr.localstorage) {
                var storageData = angular.fromJson(localStorage.options);
                if (storageData) {
                    return angular.fromJson(storageData);
                }
            }

            return {
                background: {
                    enabled: true,
                    enableSnow: true,
                    opacity: 0.6
                }
            };
        };

        function save(options) {
            if (typeof Modernizr == 'object' && Modernizr.localstorage) {
                localStorage.options = angular.toJson(options);
                $rootScope.$options = get();
            }
        };
    };
})();

我想知道因为我将它们包装在执行自己的匿名函数中,是什么导致了这个问题?

*解决方案*

所以最后我发现究竟是什么导致了这个问题。这确实与 karma.conf.js 中的文件有关。我已经告诉它加载所有文件,并且在那里有一些它不喜欢的东西。 经过一段时间的游戏后,我终于找到了它的样子,并认为我会分享它以防万一其他人来到这里。

问题是路线。我正在使用 ui.router ,看来在测试中使用它们会失败。 我将文件部分更改为:

'src/app/app.module.js',
'src/app/**/*module.js',
'src/app/**/*constants.js',
'src/app/**/*service.js',
'src/app/**/*controller.js',
//'src/app/**/*routes.js',

'test/spec/**/*.js'

正如您所看到的,我已将路径文件注释掉了。如果我把它们带回来,一切都会失败。

1 个答案:

答案 0 :(得分:0)

我认为你的内部deliveryDatesService变量正在隐藏外部变量。

为避免这种情况,您可以尝试按照以下网站上的规范在内部服务变量周围加下下划线:

https://docs.angularjs.org/api/ngMock/function/angular.mock.inject

寻找

  

'解决参考文献(下划线包裹)'

在该页面上。

然后你的代码看起来像这样:

beforeEach(inject(function (_deliveryDatesService_) {
         console.log(_deliveryDatesService_);
         service = _deliveryDatesService_;
         reasons = {};
         dateReasons = [{ value: 'D4' }];
}));

此外,您需要确保在karma.conf.js中声明所有必需的文件和目录,以便测试框架可以使用它们。