【问题标题】:angular karma unit test using $httpBackend + $resource without bootstrapping with module使用 $httpBackend + $resource 的角度业力单元测试,无需使用模块引导
【发布时间】:2016-02-20 01:24:59
【问题描述】:

要求

  • 基于 Angular 的 REST 客户端组件
  • 必须在私有 API 和服务之间进行交互
  • Karma/Jasmine 测试不引导应用程序模块

当前的困境

我们不想引导整个应用程序进行单元测试(使用 module() 或 angular.mock.module())。尽管 Angular 的组件注册是一个有用的功能,但它对于企业级应用程序来说似乎是不可持续的。我发现的所有示例都是这样做的,但是根据我们当前的业务目标,我需要在不引导应用程序模块的情况下这样做。

到目前为止,我已经成功注入了 $resource 和 $httpBackend 并且它们都可以正常工作。我可以为 $httpBackend 对象分配响应行为,并且可以将 $resource 注入测试套件中的 restClient 工厂。但是,当我尝试运行它时,它们似乎并不知道彼此,因此客户端实际上正在发送调用(不受欢迎的#1),让 $httpBackend 对象等待着非常好的期望并且没有任何东西可以刷新(#2) .

请帮忙

您能否指出我缺少的配置错误,以便在不调用 module() 的情况下使这两个部分协同工作?

测试错误

Error: No pending request to flush !
        at Function.$httpBackend.flush (node_modules/angular-mocks/angular-mocks.js:1544:34)
        at Object.<anonymous> (/var/folders/8h/lqyqq1ks6vv8z5mpsxjqn5sw0000gn/T/89bece8e9480f44013f53b3f1b05b4ba.browserify:855:22 <- src/app/services/restClient_test.js:24:0)
Error: Unsatisfied requests: GET https://ourlink.nl
        at Function.$httpBackend.verifyNoOutstandingExpectation (node_modules/angular-mocks/angular-mocks.js:1577:13)
        at Object.<anonymous> (/var/folders/8h/lqyqq1ks6vv8z5mpsxjqn5sw0000gn/T/89bece8e9480f44013f53b3f1b05b4ba.browserify:847:22 <-

来自失败的 restClient XHR 的浏览器错误

XMLHttpRequest cannot load undefinedhttps://oursite.nl?userId=UserZ. Cross origin requests are only supported for protocol schemes: http, data, chrome, chrome-extension, https, chrome-extension-resource.

restClient.js:

function restClient ($resource, baseUrl) {
    'use strict';

    return {
        get: get
    };

    function get (route, options) {
        var self = this;
        var payload = $resource(self.baseUrl + route, options).get(options.routeParams);
        return payload;
    }
}

module.exports = restClient;

restClient_test.js:

describe('restClient', function () {
    var client, $httpBackend;

    beforeEach(inject(function(_$httpBackend_) {
        $httpBackend = _$httpBackend_;
    }));

    beforeEach(function () {
        var $injector = angular.injector(['ng', 'ngResource']);
        this.client = require('./restClient.js');
        client = this.client($injector.get('$resource'));
    });

    afterEach(function() {
        $httpBackend.verifyNoOutstandingExpectation();
        $httpBackend.verifyNoOutstandingRequest();
    });

    it('sends a get request', function () {
        $httpBackend.expectGET('https://oursite.nl')
            .respond('200', {userId: 'UserZ'}, {token: '1234'});
        client.get('https://oursite.nl', {userId: 'UserZ'});
        $httpBackend.flush();
    });
});

【问题讨论】:

  • 你认为它是如何工作的?您继续使用“注入”,但不想使用“模块”。因此,您的 $injector 与 ngMock 使用的不同。 ngMock 是框架的一部分(非常有用且经过深思熟虑的部分),您应该喜欢它或离开它,就像任何框架一样。
  • 我们正在使用 ngMock,这是我们可以访问注入的地方。我不应该需要整个应用程序进行单元测试。最终,这不是我不使用 module() 引导应用程序的决定,但我认为他(我们的架构师)是有道理的。无论如何,这些都是要求。如果你不喜欢它,你不必帮忙。
  • 那么你有我的同情,这种决定和重新创建 ngMock 功能的需要不会使测试更容易。对我来说它看起来像 XY 问题,这可能是由于缺乏模块化造成的(类似于this case)。当模块的设计考虑到测试时,无需引导整个应用程序。
  • 我不确定我们是否正在重新创建功能。我们只是想要少一点功能。一个代码单元应该可以作为一个单元进行测试。这就是我们所追求的。现在我们让它工作了,它实际上非常好。
  • 您可能经常会偶然发现过度的“一个组件,一个模块”模块化,例如'foo.bar.bazController'。在生产代码中可能有点冗长,因为 JS 缺少命名空间功能,但解耦单元测试正是它的用途。

标签: javascript angularjs rest jasmine karma-runner


【解决方案1】:

如果不使用 ngMock Jasmine/Mocha 助手,它必须是这样的:

describe('restClient', function () {
    var $injector, client, $httpBackend;

    beforeEach(function () {
        $injector = angular.injector(['ng', 'ngResource', 'ngMock']);
        $httpBackend = $injector.get('$httpBackend');
        this.client = require('./restClient.js');
        client = this.client($injector.get('$resource'));
    });
    ...
});

【讨论】:

  • 您确实在此帮助下拯救了这一天。我是如此接近!比你,@estus
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-10-17
  • 2014-11-02
  • 1970-01-01
  • 2014-08-20
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多