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

Why should I mock HTTP requests inside unit tests?

本文关键字:HTTP 请求 模拟 单元测试 为什么      更新时间:2023-09-26

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

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

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

如果你想测试一个向你的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;
    };
});

这是一个简单的茉莉测试:

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被破坏了,你的PersonService测试不会在相关API测试之外被破坏。

你想要构建的是集成测试