如何使用 Karma 上的 Jasmine 将模拟依赖注入到角度指令中

2023-11-25

我有以下指令:

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 = '<div top-level-menu></div>';
        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 and $userDetails.gravatar to 'test name' and 'test avatar'分别。

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


要加载模板文件,您必须配置karma-ng-html2js-preprocessor在业力中。

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

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

这告诉 karma 加载模板文件夹中的所有 html 文件(如果您的模板位于其他位置,则将该文件夹放在那里)。

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

这告诉 karma 通过ng-html2js预处理器,然后将它们转换为角度模块,将模板放入$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是位于的外部服务角度模拟.js.

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

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

$provide是为您的提供商提供的服务。因此,如果您想注入模拟依赖项,您可以在此处重写提供程序。

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

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何使用 Karma 上的 Jasmine 将模拟依赖注入到角度指令中 的相关文章

随机推荐