如何在Karma上使用Jasmine将一个模拟依赖项注入到angular指令中

 陈醉在线wx 发布于 2023-02-09 08:55

我有以下指令:

function TopLevelMenuDirective ($userDetails, $configuration) {
    return {
        restrict:'A',
        templateUrl: staticFilesUri + 'templates/TopLevelMenu.Template.html', 
        scope: {
            activeTab: '='
        },
        link: function (scope, element, attributes) {
            var userDetails = $userDetails;
            if ($userDetails) {
                scope.user = {
                    name: userDetails.name ? userDetails.name : 'KoBoForm User',
                    avatar: userDetails.gravatar ? userDetails.gravatar: (staticFilesUri + '/img/avatars/example-photo.jpg')
                };
            } else {
                scope.user = {
                    name: 'KoBoForm User',
                    avatar: staticFilesUri + '/img/avatars/example-photo.jpg'
                }
            }

            scope.sections = $configuration.sections();

            scope.isActive = function (name) {
                return name === scope.activeTab ? 'is-active' : '';
            }
        }
    }
}

我想模拟依赖项,以使用单元测试已知的值对不同的代码路径进行单元测试.我有以下样本单元测试:

it('should set $scope.user to values passed by $userDetails', 
    inject(function($compile) {
        var element = '
'; element = $compile(element)($scope); $scope.$apply(); expect(element.isolateScope().user.name).toBe('test name'); expect(element.isolateScope().user.avatar).toBe('test avatar'); } ));

这给了我两个问题.

首先,由于模板位于外部文件中,因此当它加载时,它会尝试获取它并因错误而无法找到文件,这是合乎逻辑的,因为它位于测试环境而不是实际的服务器中.

其次,没有明显的方法可以通过构造函数来模拟注入到指令中的依赖项.在测试控制器时,您可以使用该$controller服务,但由于通过编译带有传递范围的html标记间接实例化指令,因此无法直接实例化它(例如,没有类似的$directive).这妨碍了我的设置$userDetails.name,并$userDetails.gravatar'test name''test avatar'分别.

如何正确编译指令并使用自定义$ userDetails依赖项运行?

1 个回答
  • 要加载模板文件,您必须karma-ng-html2js-preprocessor在karma中配置.

    首先,请访问此页面并按照安装说明进行操作.然后,您需要在karma.config.js文件中添加几个条目:

    files: [
        'templates/*.html'
    ],
    

    这告诉karma加载模板文件夹中的所有html文件(如果你的模板在其他地方,把那个文件夹放在那里).

    preprocessors: { '**/*.html': 'ng-html2js' },
    

    这告诉业者通过ng-html2js预处理器传递所有html文件,然后预处理器将它们转换为将模板放入$templateCache服务的角度模块.这样,当$httpBackend查询模板的"服务器"时,它会被模板缓存拦截并返回正确的html.这里一切都很好,除了模板的URL:它必须匹配templateUrl指令中的属性,ng-html2js默认情况下将完整路径作为uri传递.所以我们需要转换这个值:

    ngHtml2JsPreprocessor: {
        cacheIdFromPath: function(filepath) {
    
            var matches = /^\/(.+\/)*(.+)\.(.+)$/.exec(filepath);
    
            return 'templates/' + matches[2] + '.' + matches[3];
        }
    },
    

    它接收filepath并通过正则表达式传递它,该表达式将路径,文件名和扩展名提取到数组中.然后'templates/,您可以预先添加文件名和扩展名,然后获得预期的uri.

    完成所有这些操作后,使模板可用是在运行测试之前加载模块的问题:

    beforeEach(module('templates/TopLevelMenu.Template.html'));
    

    请记住,这module是一个位于angular-mocks.js的外部服务.

    要将自定义服务注入指令,您需要覆盖服务的提供者:

    beforeEach(module(function ($provide) {
        $provide.provider('$userDetails', function () { 
            this.$get = function () {
                return {
                    name: 'test name', 
                    gravatar: 'test avatar'
                };
            }
        });
    }));
    

    $provide是为您的提供商提供的服务.因此,如果要注入模拟依赖项,请在此处覆盖提供程序.

    在测试之前执行该代码,您将拥有一个$userDetails返回预定义字符串的模拟服务.

    2023-02-09 09:01 回答
撰写答案
今天,你开发时遇到什么问题呢?
立即提问
热门标签
PHP1.CN | 中国最专业的PHP中文社区 | PNG素材下载 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有