为什么$ httpBackend.flush()导致意外请求?

时间:2015-04-03 00:54:58

标签: angularjs ionic-framework karma-jasmine

如果我添加flush()调用它会给我“错误:意外请求:GET templates / createAccountWithAcme.html”。为什么它告诉我一个视图模板,我该如何避免这种情况?这是一个Ionic Framework(v 1.0.0 RC2 - AngularJS)项目。

编辑:以前,我错误地省略了我尝试过的$ httpBackend.when或$ httpBackend.whenGET电话。更新代码的错误相同:

编辑2:更多细节:这是一个使用ui-router的Ionic Framework项目(v1.0.0 RC2)。当我尝试删除所有其他测试时,我仍然收到错误但是注意到它抱怨的模板是在UI路由器配置中定义的最后一个模板(在Ionic中路由器是$stateProvider)。如果我在状态定义的末尾添加了一个虚拟状态,那么它就变成了测试所抱怨的那个。所以我决定路由器必须尝试加载我的测试不期望的模板。我发布了修补程序。

describe('foo', function() {
  var $http, $httpBackend;
  $http = void 0;
  $httpBackend = void 0;
  $http = null;
  $httpBackend = null;
  beforeEach(module('acme'));
  beforeEach(inject(function($injector) {
    $http = $injector.get('$http');
    $httpBackend = $injector.get('$httpBackend');
    $httpBackend.whenGET('http://www.google.com').respond({});
  }));
  it('should have parsed genres', function() {
    console.log('foo');
    $http({
      method: 'GET',
      url: 'http://www.google.com'
    }).then(function(response) {
      console.log('success: ', response);
    }, function(error) {
      console.log(error);
    });
    $httpBackend.flush();
  });
});

3 个答案:

答案 0 :(得分:3)

我最终将所有html模板列入白名单:

beforeEach ...

//this line solves it
$httpBackend.whenGET(/templates/.*/).respond(200, '');

$httpBackend.whenGET('http://www.google.com').respond({});

...

答案 1 :(得分:1)

在单元测试指令中包含其他指令的模板时,我看到了类似的HTML问题请求。

我/我们采用的一般解决方案是添加一些构建步骤,将所有项目的HTML模板“编译”(排序)到一个JS文件中,然后将该JS文件包含在karma中包含的javascript列表中.conf.js。现在,当指令加载并向模板的模板缓存发出请求时,模板已经被加载(因为你的JS是通过karma.conf.js包含的),然后没有意外的GET请求!

另请注意,作为构建过程的一部分,这通常是一件好事,因此您的客户端浏览器不会为HTML模板发出N个额外的HTTP请求。

如果您使用的是基于node.js的项目,则可以使用ng-htmljs将所有模板转换为js。他们的文档也解释了问题:https://www.npmjs.com/package/ng-html2js。这也可以通过grunt - https://www.npmjs.com/package/grunt-html2js和gulp - https://www.npmjs.com/package/gulp-ng-html2js方便地包裹。

更详细的node.js grunt解决方案:

GruntFile.coffee:

grunt.initConfig
  html2js:
    test:
      src: ['all/my/html_templates/**/*.html']
      dest: 'app/.tmp/templates.js'
    options:
      base : 'app/'
      module: 'myAppTemplates'
      singleModule: true
      htmlmin:
        collapseWhitespace: false
        collapseBooleanAttributes: true
        removeCommentsFromCDATA: true
        removeOptionalTags: true

grunt.registerTask 'test', [
  ...
  'html2js:test'
  'karma:unit'
  ...
]

在Karma.conf.js中:

files: [
  ...
  'app/.tmp/templates.js'
],

在测试中不要忘记包含模板模块:

beforeEach module 'myAppTemplates'
#or if you are using browserify:
beforeEach window.angular.mock.module 'myAppTemplates'

答案 2 :(得分:0)

您需要做的是在beforeEach条款中模拟您的请求:

 beforeEach(inject(function($injector) {
    $http = $injector.get('$http');
    $httpBackend = $injector.get('$httpBackend');
    $httpBackend.whenGet('http://www.google.com')
    .respond('Some return');
  }));

当你执行.flush()时,get方法的承诺将被解决