Angularjs AngurJS中的模拟后端服务器(谷歌表单)

Angularjs AngurJS中的模拟后端服务器(谷歌表单),angularjs,unit-testing,mocking,httprequest,karma-jasmine,Angularjs,Unit Testing,Mocking,Httprequest,Karma Jasmine,我正在使用AngularJs控制器将数据从表单发送到Google表单。我使用Jasmine编写了单元测试,它提出了以下问题: Error: Unsatisfied requests: POST http://localhost:5000/google-form at Function.$httpBackend.verifyNoOutstandingExpectation (.../angular-mocks/angular-mocks.js:1474:13) 在谷歌搜索并浏览了stackow

我正在使用AngularJs控制器将数据从表单发送到Google表单。我使用Jasmine编写了单元测试,它提出了以下问题:

Error: Unsatisfied requests: POST http://localhost:5000/google-form
at Function.$httpBackend.verifyNoOutstandingExpectation 
(.../angular-mocks/angular-mocks.js:1474:13)
在谷歌搜索并浏览了stackowerflow中的一些内容后,我决定发布这个问题,因为我没有找到解决方案

以下是供您参考的代码:

角度控制器

/* global $ */
'use strict';
angular.module('myApp')
  .controller('QuickMessageCtrl', ['$scope', function ($scope) {
    $scope.quickMessageButtonText = 'Send';
    $scope.quickMessage = {
      name: '',
      email: '',
      content: '',
    };

    function setSubmittingIndicators() {
      $scope.quickMessageButtonText = '';
      $scope.submitting = true;
    }

    $scope.postQuickMessageToGoogle = _.throttle(function() {
      setSubmittingIndicators();
      $.ajax({
        url: 'https://docs.google.com/forms/d/MyFormKey/formResponse',
        data: {
          'entry.3'  : $scope.quickMessage.name,
          'entry.1'  : $scope.quickMessage.email,
          'entry.0'  : $scope.quickMessage.content
        },
        type: 'POST',
        dataType: 'jsonp',
        statusCode: {
          200: function (){
            //show succes message;
          }
        }
      });
    }, 500);
  }]);
/* global $ */
'use strict';
angular.module('myApp')
  .controller('QuickMessageCtrl', ['$scope', 'MyNewService', function ($scope, MyNewService) {
    $scope.quickMessageButtonText = 'Send';
    $scope.quickMessage = {
      name: '',
      email: '',
      content: '',
    };

    function resetFormData() {
      $('#name').val('');
      $('#email').val('');
      $('#content').val('');
    }

    $scope.postQuickMessageToGoogle = _.throttle(function() {
      setSubmittingIndicators();
      MyNewService.sendQuickMessage(
        $scope.quickMessage.name,
        $scope.quickMessage.email,
        $scope.quickMessage.content
      )
      .success(
        //sucess Message
        //can be as well a function that returns a status code
      )
      .error(
        //error Message
      );
    }, 500);
  }]);
单元测试代码

'use strict';

describe('Controller: QuickMessageCtrl', function() {
    var $httpBackend, $rootScope, $controller, scope, apiUrl; 

    beforeEach(module('myApp'));

    beforeEach(inject(function($injector) {
        $httpBackend = $injector.get('$httpBackend');
        apiUrl = $injector.get('apiUrl');
        $httpBackend.expect(
            'POST',
            apiUrl + 'google-form',
            {'name': 'test', 'email': 'test@test.com', 'content': 'this is content'}
        ).respond(200);

        $rootScope = $injector.get('$rootScope');
        scope = $rootScope.$new();
        $controller = $injector.get('$controller');
        $controller('QuickMessageCtrl', { $scope: scope });
    }));

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

    describe('Successful form submit', function() {
        beforeEach(function() {
            scope.quickMessageForm = { $valid: true };
            scope.quickMessage.email = 'test@test.com';
            scope.quickMessage.name = 'test';
            scope.quickMessage.content = 'this is test';
            scope.postQuickMessageToGoogle();
        });

        it('should set submitting indicators on submit', function() {
            expect(scope.quickMessageButtonText).toBe('');
        });

    });
});
'use strict';
angular.module('myApp')
  .factory('MyNewService', ['$http', function ($http) {
    var myService = {};

    myService.sendQuickMessage = function(name, email, content) {
      $http({
        method: 'JSONP',
        url: 'https://docs.google.com/forms/d/MyFormKey/formResponse?'+
          'entry.3=' + name +
          '&entry.1=' + email +
          '&entry.0=' + content
      });
    };
    return myService;
  }]);

您的测试表明,模拟http后端应该在URL处接收帖子

apiUrl + 'google-form'
给定错误消息,它是
http://localhost:5000/google-表单


但是您的控制器从未向该URL发送帖子。它向
https://docs.google.com/forms/d/MyFormKey/formResponse
。它不使用angular的$http服务,而是在背后使用jQuery

正如@JB Nizet所指出的,您使用的是jQuery而不是angular方法。事实上,你应该重构一下你的代码

它是一种将事物分开的方法,比如控制器和服务。在您的情况下,您正在控制器内使用服务。我建议您创建一个服务,然后在控制器中导入该服务。因此,这里的代码基本上是这样的:

控制器

/* global $ */
'use strict';
angular.module('myApp')
  .controller('QuickMessageCtrl', ['$scope', function ($scope) {
    $scope.quickMessageButtonText = 'Send';
    $scope.quickMessage = {
      name: '',
      email: '',
      content: '',
    };

    function setSubmittingIndicators() {
      $scope.quickMessageButtonText = '';
      $scope.submitting = true;
    }

    $scope.postQuickMessageToGoogle = _.throttle(function() {
      setSubmittingIndicators();
      $.ajax({
        url: 'https://docs.google.com/forms/d/MyFormKey/formResponse',
        data: {
          'entry.3'  : $scope.quickMessage.name,
          'entry.1'  : $scope.quickMessage.email,
          'entry.0'  : $scope.quickMessage.content
        },
        type: 'POST',
        dataType: 'jsonp',
        statusCode: {
          200: function (){
            //show succes message;
          }
        }
      });
    }, 500);
  }]);
/* global $ */
'use strict';
angular.module('myApp')
  .controller('QuickMessageCtrl', ['$scope', 'MyNewService', function ($scope, MyNewService) {
    $scope.quickMessageButtonText = 'Send';
    $scope.quickMessage = {
      name: '',
      email: '',
      content: '',
    };

    function resetFormData() {
      $('#name').val('');
      $('#email').val('');
      $('#content').val('');
    }

    $scope.postQuickMessageToGoogle = _.throttle(function() {
      setSubmittingIndicators();
      MyNewService.sendQuickMessage(
        $scope.quickMessage.name,
        $scope.quickMessage.email,
        $scope.quickMessage.content
      )
      .success(
        //sucess Message
        //can be as well a function that returns a status code
      )
      .error(
        //error Message
      );
    }, 500);
  }]);
服务

'use strict';

describe('Controller: QuickMessageCtrl', function() {
    var $httpBackend, $rootScope, $controller, scope, apiUrl; 

    beforeEach(module('myApp'));

    beforeEach(inject(function($injector) {
        $httpBackend = $injector.get('$httpBackend');
        apiUrl = $injector.get('apiUrl');
        $httpBackend.expect(
            'POST',
            apiUrl + 'google-form',
            {'name': 'test', 'email': 'test@test.com', 'content': 'this is content'}
        ).respond(200);

        $rootScope = $injector.get('$rootScope');
        scope = $rootScope.$new();
        $controller = $injector.get('$controller');
        $controller('QuickMessageCtrl', { $scope: scope });
    }));

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

    describe('Successful form submit', function() {
        beforeEach(function() {
            scope.quickMessageForm = { $valid: true };
            scope.quickMessage.email = 'test@test.com';
            scope.quickMessage.name = 'test';
            scope.quickMessage.content = 'this is test';
            scope.postQuickMessageToGoogle();
        });

        it('should set submitting indicators on submit', function() {
            expect(scope.quickMessageButtonText).toBe('');
        });

    });
});
'use strict';
angular.module('myApp')
  .factory('MyNewService', ['$http', function ($http) {
    var myService = {};

    myService.sendQuickMessage = function(name, email, content) {
      $http({
        method: 'JSONP',
        url: 'https://docs.google.com/forms/d/MyFormKey/formResponse?'+
          'entry.3=' + name +
          '&entry.1=' + email +
          '&entry.0=' + content
      });
    };
    return myService;
  }]);
单元测试

'use strict';

describe('Controller: QuickMessageCtrl', function() {
  var $httpBackend, $rootScope, $controller, scope, apiUrl;

  beforeEach(module('myApp'));

  beforeEach(inject(function($injector) {
    $httpBackend = $injector.get('$httpBackend');
    apiUrl = $injector.get('apiUrl');
    $httpBackend.expectJSONP(
      'https://docs.google.com/forms/d/MyFormKey/formResponse?'+
      'entry.3=test'+
      '&entry.1=test@test.com'+
      '&entry.0=thisIsContent'
    ).respond(200, {});

    $rootScope = $injector.get('$rootScope');
    scope = $rootScope.$new();
    $controller = $injector.get('$controller');
    $controller('QuickMessageCtrl', { $scope: scope });
  }));

  describe('form submit', function() {
    var changeStateSpy;
    beforeEach(function() {
      scope.quickMessage.name = 'test';
      scope.quickMessage.content = 'thisIsContent';
      scope.quickMessage.email ='test@test.com';
    });

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

    it('should set submitting indicators on submit', function() {
      scope.postQuickMessageToGoogle();
      expect(scope.quickMessageButtonText).toBe('');
      $httpBackend.flush();
    });
  });
});