单元测试angular指令templateUrl(包括requirejs和ng-html2js

时间:2014-08-21 16:23:31

标签: angularjs unit-testing requirejs karma-runner

我正在开发一款尚未成熟的角度应用程序。我遇到了业力单元测试的问题。总而言之,我使用带有requirej的角度。如果我将模板嵌入到我的指令中,我的测试运行良好。但是,由于这个应用程序将是巨大的,它将无法扩展。但是当我移动模板并使用templateUrl在我的指令中加载它时,我无法摆脱以下错误之一(取决于我如何修改conf):

  1. (初始错误)“意外请求:GET路径/到/ mytpl.html”

  2. “ReferenceError:找不到变量:angular”。使用不同的配置会出现此错误:

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

  4. 注意:我没有在karma.conf中使用FQN,我在这里使用它是一致的。我认为这不重要,但我更倾向于确切地说明

    我看到有人将每个'path/to/mytpl.html': {deps: ['angular']}放入test-main.js的垫片部分。但它对我不起作用,并且该解决方案不会扩展。

2 个答案:

答案 0 :(得分:2)

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

假设您的指令具有templateUrl的'app / directive / myDirective.html'值。然后:

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

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

    当然你可以使用像*或**这样的外卡字符,但为了排除故障,我会从一个完整的路径值开始。根据karma配置中basePath的值,'path_to_directive'将与应用中的路径相同或不同。

    例如:如果业力基础路径距离您的应用根目录一级,那么您的'path_to_directive'='某个文件夹 /app/directive/myDirective.html'

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

    在进行此测试时请注意:

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

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

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

      ngHtml2JsPreprocessor: { stripPrefix: 'modulePrefix' }

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

      ngHtml2JsPreprocessor: { prependPrefix: 'missingPart' }

    重启业力并确保步骤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'));
            //...
        });
    });
    
  7. 我希望通过完成这6个步骤,你将得到一个有效的测试。祝你好运。

答案 1 :(得分:0)

暂时搁置这个问题并利用这段时间来提高我的知识并拓宽我的应用程序后,我找到了解决方案。

简要方法概述:as karma-ng-html2js-preprocessor karma-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. 的路径
  4. 填充它,仍然需要配置测试,以确保在角度shim: [ 'templates' : 'angular', ...]之前不会加载
  5. 在我的测试文件define(['templates',...], function(){...});
  6. 中加载此模块
  7. 检索测试指令的模板beforeEach(module('path/to/mytpl.html'));
  8. 在您的grunt配置中添加一个步骤,以便在运行测试之前自动生成它。
  9. 这就是全部!

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