【问题标题】:karma + jasmine + angular + http GET's on every testkarma + jasmine + angular + http GET 在每个测试中
【发布时间】:2016-03-09 15:45:45
【问题描述】:

作为应用引导程序的一部分,它通过一系列 HTTP GET 来加载资产。

如果我不考虑获取,我的单元测试将抛出“意外的 GET 请求”。问题是我必须在每个测试中包含 GET。下面大约有十几个。

$httpBackend.when('GET', 'assets/iconsets/action-icons.svg').respond('ok');

我的问题是;有没有更好的全局方法来在一个地方解释 GET 并将该调用包含在我的所有测试中?

编辑:

下面是我必须包含在每个规范文件中的整个假设块。我宁愿在某个地方声明这个块一次,可能是全局代码可以执行的地方。

$httpBackend.when('GET', 'assets/iconsets/action-icons.svg').respond('ok');
$httpBackend.when('GET', 'assets/iconsets/alert-icons.svg').respond('ok');
$httpBackend.when('GET', 'assets/iconsets/av-icons.svg').respond('ok');
$httpBackend.when('GET', 'assets/iconsets/communication-icons.svg').respond('ok');
$httpBackend.when('GET', 'assets/iconsets/content-icons.svg').respond('ok');
$httpBackend.when('GET', 'assets/iconsets/device-icons.svg').respond('ok');
$httpBackend.when('GET', 'assets/iconsets/editor-icons.svg').respond('ok');
$httpBackend.when('GET', 'assets/iconsets/file-icons.svg').respond('ok');
$httpBackend.when('GET', 'assets/iconsets/hardware-icons.svg').respond('ok');
$httpBackend.when('GET', 'assets/iconsets/image-icons.svg').respond('ok');
$httpBackend.when('GET', 'assets/iconsets/maps-icons.svg').respond('ok');
$httpBackend.when('GET', 'assets/iconsets/mdi-icons.svg').respond('ok');
$httpBackend.when('GET', 'assets/iconsets/navigation-icons.svg').respond('ok');
$httpBackend.when('GET', 'assets/iconsets/notification-icons.svg').respond('ok');
$httpBackend.when('GET', 'assets/iconsets/social.svg').respond('ok');
$httpBackend.when('GET', 'assets/iconsets/social-icons.svg').respond('ok');
$httpBackend.when('GET', 'assets/iconsets/toggle-icons.svg').respond('ok');
$httpBackend.when('GET', 'assets/iconsets/editor-icons.svg').respond('ok');

【问题讨论】:

  • 您可以使用beforeEach method 定义一组测试的期望值。我的问题是:为什么要引导整个应用程序运行单元测试?
  • 你是对的。我在每个规范文件中都包含了 beforeEach... 中的假设块。有没有办法引用一个可以执行假设的地方,我可以将它们包含在规范文件中?
  • 由于angular.mock.module('myHomeSearch');,我认为我不能通过 Angulars 引导程序。一旦运行,它将运行 Angular 的配置块。

标签: angularjs unit-testing jasmine karma-runner


【解决方案1】:

$httpBackend.when 接受一个函数作为 url 部分,如 api 文档 here 中所述,因此如果您不介意将其放在每个规范的顶部,您可以这样做:

$httpBackend.when('GET', function(url){
   //do your custom evaluations here (or just return true for everything...)
   if(url_is_like_any_of_yours){
     return true;
   }
}).respond('ok');

如果你想让它全局化,另一个选择是你可以使用装饰器直接拦截 $http 调用。在我的示例中,其 url 在列表中的每个 $http.get 调用都将返回文本“ok”。您可以将此文件包含在您的 karma.conf 中,就像它是一个规范一样,它应该为每个测试运行。

angular.module('app').config(function($provide) {
    $provide.decorator('$http', function($delegate, $injector) {
        var originalGet = $delegate.get;
        //override the get function of $http and return a resolved promise
        $delegate.get = function(url, config) {
            var ignoreUrls = ['assets/iconsets/alert-icons.svg', 'assets/iconsets/av-icons.svg'];
            //if the url is not one that we are trying to ignore, let the request go through.
            if (ignoreUrls.indexOf(url) === -1) {
                return originalGet(url, config);
            }

            //the url is one we would like to ignore, so just return a promise with a fake http response 
            var fakeHttpResponse = {
                "data": "ok",
                "status": 200,
            };
            var $q = $injector.get('$q');
            var deferred = $q.defer();
            deferred.resolve(fakeHttpResponse);
            return deferred.promise;
        }
        return $delegate;
    });
});

只需确保将此文件包含在 angular.js 文件之后以及模块声明 angular.module('nameOfYourModule', []) 之后。

这是我用来测试的 karma 文件的一部分。

module.exports = function(config) {
  config.set({
    // list of files / patterns to load in the browser
    files: [
        //include angular and angular-mocks first
        'lib/angular/angular.js',
        'lib/angular/angular-mocks.js',
        //include your module declaration, the file with angular.module('app', []) in it
        'src/app.js',
        //include the http decorator file
        'specs/httpDecorator.js',
        //now include the rest of your source files and specs
        'src/**/*.js',
        'specs/**/*.js'
    ]
  });
} 

【讨论】:

  • 我认为我的问题措辞错误。每个规范文件(使用 $timeout.flush())都必须有 14 个 $httpBackend.when() 调用来说明在引导期间获取的资产。如果我不包括它们,测试将失败。我想知道是否有一个全局区域,我可以在其中包含一次 when() 调用,而不是在每个规范文件中声明它们。请参阅已编辑。
  • 我设法将规范包含在 conf 中,但收到错误 'undefined' is not an object (evaluating 'set.querySelector')。有什么线索吗?
  • @0101adm,我再次更新了我的答案,以更好地解释如何将其纳入业力。在 karma 配置中,在 files 数组中,确保首先出现 angular,然后是包含 angular.module('yourModuleName', []) 代码的文件,然后你可以包含这个 http 拦截器文件。
  • 你使用的是什么版本的角度?
  • 你完全正确。这是被返回的内容。用通过测试的实际数据替换“ok”。我要做的是,如果找到了 url,我会在那里进行提取并将数据包含在返回的“数据”成员中。再次感谢!太棒了。
猜你喜欢
  • 2015-12-07
  • 1970-01-01
  • 2018-01-31
  • 2015-12-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-02-21
相关资源
最近更新 更多