【问题标题】:Angular + Karma + Jasmine - Testing and app with a fake backendAngular + Karma + Jasmine - 带有假后端的测试和应用程序
【发布时间】:2014-06-06 12:34:16
【问题描述】:

我正在开发一个有角度的 WebApp,由于后端尚未准备好,我正在使用假后端 ($httpBackend) 来测试我的 REST 请求。

在app.js中是这样定义的:

// we want to use $httpBackend mock
app.config(function($provide) {
  $provide.decorator('$httpBackend', angular.mock.e2e.$httpBackendDecorator);
});
// define our fake backend
app.run(function($http, $httpBackend, url) {
  //Escape string to be able to use it in a regular expression
    function regEsc(str) {
        return str.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&");
    }

  // Mocking the login request
  //define the success var
  var user = {username: "me@stuff.it", password: "pass"};
  var userResponse = {
       "succes": "true",
       "user":{
       "id":"8490394",
       "username": "me",
       "token": "asd8u09u900asduijjaijjHJ"
      }
  };
  //success case
  $httpBackend.whenPOST(url.login, user).respond(200,userResponse);

  //other cases
  $httpBackend.whenPOST(url.login).respond(403,{success: false, message: 'Wrong username or password'});

  //let pass all views request
  $httpBackend.whenGET(function(string){
    console.log(string);
    return true;
  }).passThrough();

  $httpBackend.whenGET( RegExp( regEsc( "views/" ) ) ).passThrough();
});

当我使用grunt serve 运行应用程序时,它可以正常工作

当我尝试运行我编写的测试(在 Jasmine 中并通过 Karma 执行)时,问题就开始了,这里是一个示例测试:

'use strict';

describe('Service: Loginservice', function () {

  // load the service's module
  beforeEach(module('cmmApp'));

  // instantiate service
  var Loginservice, $rootScope, $httpBackend, url;
  beforeEach(inject(function (_Loginservice_, _$rootScope_ , $injector, _url_) {
    Loginservice = _Loginservice_;
    $rootScope = _$rootScope_;
    url = _url_;

    //questo serve per iniettare httpBackend
    $httpBackend = $injector.get('$httpBackend');

    $httpBackend.when('POST', url.login, {username:     "me@stuff.it",password:"pass"}).respond({success: true, user:{"id":"8490394","username": "me","token": "asd8u09u900asduijjaijjHJ"}});

    $httpBackend.whenPOST(url.login).respond(403, {success: false, message: 'Wrong username or password'});
  }));

it('should return user object', function () {

    var f;

    //se i valori sono corretti ritona un oggetto che contiene l'utente
    inject(function(Loginservice, $rootScope){
      Loginservice.login({username:"me@stuff.it",password:"pass"}).then(function(res){
        f = res;
      }); //end login

      //this trigger the promise
      $rootScope.$digest();

      //this trigger the http request
      $httpBackend.flush();

      expect(f).toEqual({success: true, user:{"id":"8490394","username": "me","token": "asd8u09u900asduijjaijjHJ"}});
    }); //end inject
  });

如果我从 app.js 中删除假后端配置,它们会完美运行,而不是如果我把它留在那里 Karma 报告:Error: No pending request to flush !

我认为这是因为 app.js 中声明的拦截器被触发并阻止在请求中触发测试中定义的 $httpBackend。

关于如何解决这个问题的任何想法?

提前致谢

【问题讨论】:

    标签: angularjs unit-testing jasmine karma-runner httpbackend


    【解决方案1】:

    ngMockE2E 将使您的 httpBackend 在单元测试中无用。我在同样的事情上挣扎。我现在一直将我所有的模拟对象放在一个模块中,my.mocks 或其他任何东西,然后在 e2e 测试和单元测试中使用它。

    对于 e2e 测试和后端开发,我有一个 appDev 模块,该模块被引导并需要 app 模块、my.mocks 模块和 ngMockE2E 模块。

    对于单元测试,我加载了app,然后模拟与我的 appDev 代码的 when() 基本相同,复制东西对我来说确实很愚蠢,但同时我经常想使用除了 e2e 响应之外,我发现自己还有一些自定义单元测试响应。

    【讨论】:

      【解决方案2】:

      $httpBackend 不会让您的生活变得轻松,而且它非常以角度为中心,这意味着您的应用程序中的任何 XHR 不是通过 Angular 完成的都不会返回您定义的虚假数据。

      另一种方法是使用monkey-patch XMLHttpRequest 拦截对您要模拟的服务的调用,并将它们传递给在客户端运行的伪RESTful 服务。这正是FakeRest 所做的,所以你可能想看看它。

      【讨论】:

        猜你喜欢
        • 2015-12-07
        • 1970-01-01
        • 1970-01-01
        • 2016-08-23
        • 2016-06-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-01-31
        相关资源
        最近更新 更多