为什么要在单元测试中模拟 HTTP 请求?

woo*_*gie 6 javascript unit-testing jasmine angularjs

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

Chr*_*tin 5

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


Jon*_*onn 4

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

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

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

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;
    };
});
Run Code Online (Sandbox Code Playgroud)

这是一个简单的 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);
    });
});
Run Code Online (Sandbox Code Playgroud)

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

为了确保一切正常工作,您想要构建的是集成测试