gpt4 book ai didi

unit-testing - 如何在 Karma 上使用 Jasmine 将模拟依赖项注入(inject) Angular 指令

转载 作者:行者123 更新时间:2023-12-04 02:31:30 24 4
gpt4 key购买 nike

我有以下指令:

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');
}
));

这给了我两个问题。

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

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

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

最佳答案

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

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

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

这告诉 karma 加载模板文件夹中的所有 html 文件(如果您的模板在其他地方,则将该文件夹放在那里)。
preprocessors: { '**/*.html': 'ng-html2js' },

这告诉 karma 通过 ng-html2js 传递所有 html 文件。预处理器,然后将它们转换成 Angular 模块,将模板放入 $templateCache服务。这样,当 $httpBackend查询模板的“服务器”,它被模板缓存拦截并返回正确的 html。一切都很好,除了模板的 URL:它必须匹配 templateUrl指令中的属性和 ng-html2js默认情况下将完整路径作为 uri 传递。所以我们需要转换这个值:
ngHtml2JsPreprocessor: {
cacheIdFromPath: function(filepath) {

var matches = /^\/(.+\/)*(.+)\.(.+)$/.exec(filepath);

return 'templates/' + matches[2] + '.' + matches[3];
}
},

这收到 filepath并通过 regular expression将路径、文件名和扩展名提取到数组中。然后在前面加上 'templates/到文件名和扩展名,你会得到预期的 uri。

在完成所有这些之后,使模板可用是在运行测试之前加载模块的问题:
beforeEach(module('templates/TopLevelMenu.Template.html'));

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

要将自定义服务注入(inject)指令中,您需要覆盖服务的提供者:
beforeEach(module(function ($provide) {
$provide.provider('$userDetails', function () {
this.$get = function () {
return {
name: 'test name',
gravatar: 'test avatar'
};
}
});
}));
$provide是为您的提供者提供的服务。所以,如果你想注入(inject)一个模拟依赖,你可以在这里覆盖提供者。

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

关于unit-testing - 如何在 Karma 上使用 Jasmine 将模拟依赖项注入(inject) Angular 指令,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20694690/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com