Angular / Karma - 预期和观察到的请求相同时出现“意外请求”错误

时间:2014-11-26 17:12:10

标签: javascript angularjs unit-testing karma-runner

我是一个单元测试控制器的方法。我的应用程序在应用程序启动时触发了一些GET请求,并且在运行测试时我收到了意外的请求错误。

这是我的控制器的登录方法。注意:我使用了angular classy(因此是非标准语法):

login: function() {
    var self = this,
        params,
        loginSuccess,
        user;

    if (self.$.user.email === '' || self.$.user.password === '') {

      self.$notification.alert({
        title: "Error",
        message: "Email and password can't be blank!"
      });

    } else {

      params = {
         user: self.$.user,
         position: self.Geolocation.currentPosition
      };

      self.$session.login(params).then(loginSuccess);

    }
};

以下是测试:

describe("LoginController", function() {
  var scope, $rootScope, createController, $controller,
      $httpBackend, $session, session, $notification;

  var emptyCredentials = {
    email: "bleh",
    password: ""
  };

  beforeEach(angular.mock.module('myapp'));

  beforeEach(inject(function($injector){

    jasmine.getJSONFixtures().fixturesPath='base/unit/fixtures';

    $httpBackend = $injector.get("$httpBackend");

    $httpBackend
      .when('GET', 'http://myapp.com:3000/api/v2/apps/3?app_id=3')
      .respond(200, getJSONFixture('apps.json'));
    $httpBackend
      .when('GET', 'http://myapp.com:3000/api/v2.2/locations?app_id=3')
      .respond(200, getJSONFixture('locations.json'));
    $httpBackend
      .when('GET', 'http://myapp.com:3000/api/v2/users/me?app_id=3')
      .respond(200, getJSONFixture('me.json'));

    $session = $injector.get("$session");

    // mock session so that session.loggedIn doesn't return true
    // on subsequent tests
    session = {
      setUser: function() {
      },
      loggedIn: function() {
        return false;
      },
      authPath: function() {
        return false;
      },
      login: $session.login
    };

    $rootScope = $injector.get("$rootScope");
    $controller = $injector.get("$controller");
    $notification = $injector.get("$notification");
    scope = $rootScope.$new();

    createController = function () {
      return $controller('LoginController', {
        $scope: scope,
        $session: session,
        $notification: $notification
      });
    };

    // spies on $notification.alerts
    spyOn($notification, 'alert');

  }));

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

    $httpBackend.resetExpectations();

  });

  it('should show alert on empty login credentials', function() {

    $httpBackend.expectGET('http://myapp.com:3000/api/v2/apps/3?app_id=3');
    $httpBackend.expectGET('http://myapp.com:3000/api/v2.2/locations?app_id=3');
    $httpBackend.expectGET('http://myapp.com:3000/api/v2/users/me?app_id=3');

    var controller = createController();
    scope.user = emptyCredentials;
    scope.login();

    $httpBackend.flush();

    expect($notification.alert).toHaveBeenCalledWith({
      title: "Error",
      message: "Email and password can't be blank!"
    });

  });

当我经营业力时,我得到了这些错误:

Error: Unexpected request: GET http://myapp.com:3000/api/v2/apps/3?app_id=3
Expected GET http://myapp.com:3000/api/v2/apps/3?app_id=3
    at $httpBackend (/Users/myapp/vendor/angular-mocks/angular-mocks.js:1178:9)
    at sendReq (/Users/myapp/vendor/angular/angular.js:8315:9)
    at serverRequest (/Users/myapp/vendor/angular/angular.js:8049:16)
    at wrappedCallback (/Users/myapp/vendor/angular/angular.js:11520:81)
    at wrappedCallback (/Users/myapp/vendor/angular/angular.js:11520:81)
    at /Users/myapp/vendor/angular/angular.js:11606:26
    at Scope.$eval (/Users/myapp/vendor/angular/angular.js:12632:28)
    at Scope.$digest (/Users/myapp/vendor/angular/angular.js:12444:31)
    at Function.$httpBackend.flush (/Users/myapp/vendor/angular-mocks/angular-mocks.js:1438:16)
    at null.<anonymous> (/Users/myapp/test/unit/controllers/login_controller.test.js:104:18)
Error: Unexpected request: GET http://myapp.com:3000/api/v2.2/locations?app_id=3
Expected GET http://myapp.com:3000/api/v2/apps/3?app_id=3
    at $httpBackend (/Users/myapp/vendor/angular-mocks/angular-mocks.js:1178:9)
    at sendReq (/Users/myapp/vendor/angular/angular.js:8315:9)
    at serverRequest (/Users/myapp/vendor/angular/angular.js:8049:16)
    at wrappedCallback (/Users/myapp/vendor/angular/angular.js:11520:81)
    at wrappedCallback (/Users/myapp/vendor/angular/angular.js:11520:81)
    at /Users/myapp/vendor/angular/angular.js:11606:26
    at Scope.$eval (/Users/myapp/vendor/angular/angular.js:12632:28)
    at Scope.$digest (/Users/myapp/vendor/angular/angular.js:12444:31)
    at Function.$httpBackend.verifyNoOutstandingExpectation (/Users/myapp/vendor/angular-mocks/angular-mocks.js:1470:16)
    at null.<anonymous> (/Users/myapp/test/unit/controllers/login_controller.test.js:75:18)

login_controller.test.js的FYI第104行是$httpBackend.flush()。 login_controller.test.js的第75行是$httpBackend.verifyNoOutstandingExpectation()

我相信$ httpBackend.when()在应用程序启动之前被调用(因此在应用程序启动请求被触发之前),但可能这不是真的。奇怪的是,错误报告它发现XXX的意外请求,并且下一行表示它期望同一路径的请求!所以不确定为什么会这样。

运行Angular 1.2.21,Angular Mocks 1.2.21

任何人都可以向我解释为什么我会看到这个错误,以及如何正确刷新和处理这些请求?

感谢。

2 个答案:

答案 0 :(得分:1)

我弄清楚发生了什么:

事实证明,供应商插件正在扩展本机String对象,重新定义了match()方法。这与角度模拟如何将期望与请求进行比较相矛盾,因此错误地抛出了错误。

如果您碰巧遇到此问题(预期请求和观察到的请求相同),请查找扩展本机String对象的插件或库。

例如,Mootools这样做会导致这个问题。

答案 1 :(得分:0)

  

问题是现在$ http甚至对请求拦截器使用promises,因此验证在$ httpBackend获取请求之前发生。尝试添加$ rootScope。$ digest();并且你会得到&#34;不再需要请求&#34;。

参考:https://github.com/angular/angular.js/issues/5453