【问题标题】:unit testing angular directives templateUrl (include requirejs and ng-html2js单元测试 Angular 指令 templateUrl(包括 requirejs 和 ng-html2js
【发布时间】:2014-08-21 16:23:30
【问题描述】:

我正在开发一个还不算大的 Angular 应用程序。我遇到了业力单元测试的问题。长话短说,我使用 angular 和 requirej。如果我将模板嵌入我的指令中,我的测试运行良好。但由于这个应用程序很大,它不会扩展。但是当我移动模板并使用templateUrl 将其加载到我的指令中时,我无法摆脱以下错误之一(取决于我如何修改conf):

  1. (初始错误)“意外请求:GET path/to/mytpl.html”

  2. “ReferenceError:找不到变量:角度”。使用不同的配置会发生此错误:

    • 当我将 {pattern: 'path/to/mytpl.html', included: false} 放入我的 karma.conf 并在我的测试文件中添加 requirejs 的定义 path/to/mytpl.html 时(这是我希望它工作的方式)。
    • 当我将path/to/mytpl.html 放入我的 karma.conf 时,我的所有模板都会返回此错误(无论我是否使用 ng-html2-js 预处理器)。
  3. “错误:[$injector:modulerr] 无法实例化模块模板,原因是: 错误:[$injector:nomod] 模块“模板”不可用!”。我看到 karma-ng-html2js-preprocessor 可以用来创建一个包含所有模板的模块,但它从来没有工作过。

注意:我在 karma.conf 中没有使用 FQN,我在这里使用它是为了保持一致。我认为这并不重要,但我更喜欢准确地说

我看到有人将每个 'path/to/mytpl.html': {deps: ['angular']} 放在他们的 test-main.js 的 shim 部分。但这对我不起作用,而且该解决方案无法扩展。

【问题讨论】:

    标签: angularjs unit-testing requirejs karma-runner


    【解决方案1】:

    我遇到了同样的问题,并在以下article 中找到了解决方案。 我猜您的问题出在错误的业力或 requireJS 配置中,尤其是基本路径设置。 如果您的指令 templateUrl 是相对的,并且无法针对 karma 基本路径或 requireJS 基本路径正确解析该 url,那么您需要解决这个问题。

    假设您的指令在 templateUrl 中具有“app/directive/myDirective.html”值。那么:

    1. 检查您的 html 文件是否正确包含在 karma 配置的 files 部分中,注意 included:false 设置:

      files: [
          //...
          { pattern: 'path_to_directive/myDirective.html', included: false },
          //...
      ],
      

      当然,您可以使用 * 或 ** 之类的通配符,但出于故障排除的目的,我将从完整路径值开始。根据 karma config 中 basePath 的值,'path_to_directive' 将与您应用中的路径相同或不同。

      例如:如果 karma 基本路径比您的应用根目录高一级,那么您的 'path_to_directive' = 'some-folder/app/directive/myDirective.html'

    2. 确保您可以从浏览器中获取您的文件。转至http://localhost:karma_port/base/path_to_directive/myDirective.html.js

      做这个测试的时候注意:

      • url 中的 base 前缀(karma 为该虚拟路径中的所有文件提供服务,并将此前缀添加到所有 url)
      • '.js' 在您的网址末尾
    3. 在步骤 2 中获得文件后,您将看到由 html2js 预处理器创建的实际模块代码。它应该看起来像这样:

      angular.module('module_path/myDirective.html', []).run(function($templateCache) {
          $templateCache.put('module_path/myDirective.html',
          //...
      
    4. 确保 module_path 是 'app/directive/'。如果没有,那么您有 2 个选择:

      • module_path 有一些前缀 => 只需在 karma 配置中添加以下内容即可删除它:

        ngHtml2JsPreprocessor: { stripPrefix: 'modulePrefix' }

      • module_path 更短 => 添加缺失部分:

        ngHtml2JsPreprocessor: { prependPrefix: 'missingPart' }

      重启 karma 并确保步骤 3 中的 'module_path''app/directive/'

    5. 确保你已经为你的模板模块添加了角度依赖(检查 test-main.js,它基本上是 requireJS 的配置文件)。另请记住,shim 部分中的值将根据 test-main.js 文件中的 baseUrl 值进行解析。为简单起见,我假设 requireJS 可以从 'requirejs_path/myDirective.html' 路径获取文件。

      shim: {
          //..
          'requirejs_path/myDirective.html': { deps: ['angular'] },
          //..
      }
      
    6. 确保您已将模板作为测试的依赖项包含在内,并且不要忘记加载模块:

      define(['requirejs_path/myDirective.html', 'angular-mocks', '...'], function () {
      
          describe('test suite', function() {
              //...
              beforeEach(module('app/directive/myDirective.html'));
              //...
          });
      });
      

    我希望通过完成这 6 个步骤,您将获得一个有效的测试。祝你好运。

    【讨论】:

    • 感谢您的贡献,也许比我的回复更清楚。您如何看待这种方法的缺点,因为它需要检索或模拟测试指令中使用的所有其他指令的模板?
    【解决方案2】:

    在将这个问题搁置了一段时间并利用这段时间来提高我的知识并扩大我的应用程序之后,我找到了解决方案。

    简要方法回顾:作为 karma-ng-html2js-preprocessorkarma-html2js-preprocessor 似乎适用于其他一些项目,因为它们在官方中被引用doc,我尝试了许多(我认为几乎所有)可能的配置组合来在我的测试环境中运行其中一个。没有成功,我得到了线索:我必须放弃它们并找到另一种方法。

    解决方案来自 grunt-html2js。通过简单地将基本设置添加到 grunt 配置并运行 grunt,它会生成一个包含我所有模板的模块——也许,我稍后会将它拆分为更有意义的模块。但从这里开始,工作几乎完成了。然后我只需要:

    1. 告诉 karma 服务文件有其他外部工具file: [ {pattern: 'path/to/mytplmodule.js', included: false}, ...]
    2. 在我的 require conf 中注册路径以进行测试path: [ 'templates' : 'path/to/mytplmodule', ...]
    3. 填充它,仍然在 require conf 中进行测试,以确保它不会在 angular shim: [ 'templates' : 'angular', ...] 之前加载
    4. 将此模块加载到我的测试文件define(['templates',...], function(){...});
    5. 检索测试指令的模板beforeEach(module('path/to/mytpl.html'));
    6. 在您的 grunt 配置中添加一个步骤,使其在运行测试之前自动生成。

    就是这样!

    这种方法有一个缺点,它需要检索或模拟测试指令中使用的所有其他指令模板。随着指令数量的增加,这可能会很无聊。但我现在更喜欢它,因为它对应用程序的代码没有侵入性。也许以后,特别是当我将 javascript 的编译包含在我的过程中时,我也会将它从测试转移到应用程序。

    【讨论】:

    • 感谢您分享对您有用的方法。你会碰巧有一个端到端工作的 github repo(或其他东西)吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-01-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-03-01
    • 1970-01-01
    相关资源
    最近更新 更多