Why should I mock HTTP requests inside unit tests?

牧云@^-^@ 提交于 2019-12-05 13:03:04

Asserting that you shouldn't be testing the server from Jasmine is an overly simple generalization. Whether you want small tests, large tests, or some combination of both really depends on the application. One might say that it isn't a "unit" test anymore - that it's an "integration" test - but those terms have been overloaded to the point of nonsense because it's a rather artificial dichotomy. Write tests that are useful and maintainable. Choosing the size of the test is an important part of that. What size is appropriate requires your own judgement of the situation.

The idea of a unit test is to outline how a small part of an application should work. If it is passing that test, you know that it is functioning as specified.

If you want to test a service that sends requests to your API, you set up unit tests that check the location/content/existence of the outgoing requests and verifies that it responds correctly to a valid response. To make the test as specific as possible though, it should not test anything outside of that little bubble.

Let's say we want to test this PersonService angular service:

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;
    };
});

Here is a simple Jasmine test:

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);
    });
});

So we have a test that checks this very basic functionality (regardless of what the API actually does). This allows us to test pieces of the code individually---ie if the API is broken, your PersonService test won't break in addition to the related API test.

What you want to build to make sure everything works together properly is integration tests.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!