【问题标题】:Why should I mock HTTP requests inside unit tests?为什么要在单元测试中模拟 HTTP 请求?
【发布时间】:2014-06-13 00:11:23
【问题描述】:

我正在做一个项目,我们已经开始编写 Jasmine 单元测试。这个应用程序,就像任何优秀的 JS 应用程序一样,会进行大量的异步数据获取。我看到 Angular 提供了 $httpBackend 来模拟 HTTP 请求。我还阅读并听说在控制器中测试 AJAX 请求是一个坏主意,因此 $httpBackend 存在的理由。为什么测试 AJAX 调用不是一个好主意?大型 JS 应用程序如何绕过这个事实? 击中实际服务器的实际测试何时进行?

【问题讨论】:

    标签: javascript angularjs unit-testing jasmine


    【解决方案1】:

    断言您不应该从 Jasmine 测试服务器是一种过于简单的概括。无论您想要小型测试、大型测试还是两者的某种组合,实际上都取决于应用程序。有人可能会说它不再是“单元”测试——它是“集成”测试——但这些术语已经被过度使用到无意义的地步,因为它是一种相当人为的二分法。编写有用且可维护的测试。选择测试的大小是其中的一个重要部分。什么尺寸合适需要你自己判断情况。

    【讨论】:

      【解决方案2】:

      单元测试的想法是概述应用程序的一小部分应该如何工作。如果它通过了该测试,您就知道它按规定运行。

      如果您想测试向您的 API 发送请求的服务,您可以设置单元测试来检查传出请求的位置/内容/是否存在,并验证它是否正确响应了一个有效的回复。但是,为了使测试尽可能具体,它不应该测试那个小气泡之外的任何东西。

      假设我们要测试这个PersonService angular 服务:

      app.service('PersonService', function ($q, $timeout, $http) {
          this.addPerson = function(data) {
              var deferred = $q.defer();
              $http.post('api/People', data).then(function(response) {
                  deferred.resolve(response);
              });
              return deferred.promise;
          };
      });
      

      这是一个简单的 Jasmine 测试:

      var service, $httpBackend;
      beforeEach(module('app'));
      beforeEach(inject(function(_PersonService_, _$httpBackend_) {
          service = _PersonService_;
          $httpBackend = _$httpBackend_;
      }));
      
      describe('addPerson', function() {
          var person;
          beforeEach(function() {
              // Make a person to send
              person = new Person({ id: "0ff1165f-7f75-45ed-8faa-ee94d874a1cf" });
          });
      
          afterEach(function() {
              $httpBackend.verifyNoOutstandingExpectation();
              $httpBackend.verifyNoOutstandingRequest();
          });
      
          it('should send a person object to the API', function() {
              // setup
              var promise, expected, actual;
              expected = /* Whatever is sent back */
              $httpBackend.whenPOST('api/People', person)
                  .respond(expected);
      
              // act
              promise = service.addPerson(person);
              promise.then(function(response) {
                  actual = response.data;
              });
      
              $httpBackend.flush();
      
              // assert
              expect(actual).toEqual(expected);
          });
      });
      

      所以我们有一个测试来检查这个非常基本的功能(不管 API 实际做什么)。这允许我们单独测试代码片段——即如果 API 被破坏,除了相关的 API 测试之外,您的 PersonService 测试不会破坏。

      您想要构建以确保一切正常工作的是集成测试。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-08-25
        • 2014-08-28
        • 2012-07-09
        • 2015-08-27
        • 1970-01-01
        • 2011-12-20
        相关资源
        最近更新 更多