How do I unit test HTTP requests?

unit test http request c#
unit test http request java
jest mock http request
node js test get request
node intercept http request
how to mock http request
supertest
mocha test post request

As the title asks how do I test HTTP requests with Mocha and Chai?

I've recently started learning unit testing and I'm still getting confused with certain aspects of testing. I can get by fine testing methods that return a value but I'm confused on how to test methods that make HTTP/IO requests.

For example I have the following code:

module.exports = someRequest => new Promise((resolve, reject) => 
    http.get('http://google.com', resp => {
        if(resp.headers['content-type'] !== 200) {
            reject(new Error('Failed to connect to Google'));
        }
        resolve('Connected to Google');
    })
);

I want to test 2 cases:

  1. The request to Google succeed
  2. The request to Google failed

Do I have to mock these requests and if so what's the purpose of mocking a method that is intended to make a HTTP request?

Thanks in advanced.

I've used supertest in the past and was very happy with it

import server from '../src/server';
import Request from 'supertest';

describe('Server', () => {
  const request = Request(server());

  describe('/api', () => {
    it('Should return a 404 when invalid route', done => {
      request
        .post('/api/notfound')
        .expect(404)
        .end(done);
    });
  });
});

HTTP API Unit Testing, HTTP Unit Testing. When writing unit tests using this HTTP framework, don't make requests to a real server. Instead, mock the HTTP transport and inject fake HTTP requests and responses. The pluggable HTTP transport layer of the Google HTTP Client Library for Java makes this flexible and simple to do. How to Write Unit Tests to Check Your HTTP Headers (and Other HTTP Request Stuff) in C# I’ve been building a set of libraries recently that make HTTP calls into the Force.com and Chatter REST APIs and I needed to find a way to test my methods and ensure that my HTTP Requests were constructed correctly.

Try Mockttp (disclaimer: I'm the maintainer of Mockttp).

Mockttp gives you a real local HTTP server & proxy that you can easily configure & use for testing, for exactly these kind of cases.

You can either make requests to Mockttp directly, using a localhost URL, or keep making requests to google.com but use Mockttp as a proxy, and then configure whatever responses (or failed connections/timeouts) you'd like to simulate.

There's some examples in the README that show exactly what you're looking for: https://www.npmjs.com/package/mockttp#get-testing. In your specific case, I'd try something like:

const makeRequest = require("./your-code");
const mockServer = require("mockttp").getLocal();

describe("makeRequest", () => {
    beforeEach(() => mockServer.start());
    afterEach(() => mockServer.stop());

    it("resolves happily for successful requests", () => {
        await mockServer.get("http://google.com").thenReply(200, "A mocked response");

        // Here: configure your code to use mockServer.url as a proxy

        let result = await makeRequest();

        expect(response).to.equal('Connected to google');
    });

    it("rejects failed requests with an error", () => {
        await mockServer.get("http://google.com").thenReply(500, "An error!");

        // Here: configure your code to use mockServer.url as a proxy

        let result = makeRequest();

        expect(response).to.be.rejectedWith('Failed to connect to Google');
    });
});

Configuring the proxy will depend on the libraries you're using, but for http.get https://www.npmjs.com/package/global-tunnel should do it, or you can pass a { proxy: mockServer.url } option to the http.get call directly. Or of course you could make the http://google.com URL configurable, set that to mockServer.url, and mock / instead of http://google.com.

The key difference is that this is an real integration test. You're not mocking at the JS level, instead you're sending real HTTP requests, testing what will really be sent and received, and exactly how your full Node + application code will respond to that in practice.

You can mock entirely at the JS level, and your tests will be marginally quicker (in the region of 2ms vs 10ms per test), but it's very easy to get inaccurate results, and have passing tests but broken real-world functionality.

HTTP Unit Testing, When you need to test code that sends out HTTP requests, try the following. Split up the HTTP requests from your business logic of processing  Mock HTTP Request In Express Unit Testing. Inside the app.js file you have a route called /getAPIResponse which makes an HTTP request to an external API. While unit testing our application we’ll mock every external dependency. In this case the external dependency is the API call.

How about mocking http.get with something like that ?

const createHttpGetMock = (expectedStatus) => {
  return httpGetMock = (address) => {
    return new Promise((resolve, reject) => {
      resolve({
        status: expectedStatus,
        headers: {
          // ... headers
        },
        // mock response
      })
    })
  }
}

Then your test could look like this :

describe("Google request", () => {
  it("Resolves when google responds", async () => {
    const httpSuccessMock = createHttpGetMock(200);
    // Inject your mock inside your request function here, using your favorite lib

    const message = await fetchGoogle();
    assert.equals(message, 'Connected to Google');
  })

  it("Rejects when google responds with error", async () => {
    const httpSuccessMock = createHttpGetMock(500);
    // Inject your mock inside your request function here, using your favorite lib

    const message = await fetchGoogle();
    assert.equals(message, 'Failed to connect to Google');
  })
});

This would fulfill the basic contract of a good unit test : regardless of external modules and dependencies, it ensures the module you're currently testing has the correct behaviour in each possible case.

How to mock requests for unit testing in Node, How do you write a unit test for REST API? I do heartily endorse your use of readonly which doesn't get a lot of exposure. However, there are many good mocking frameworks out there that you don't need to write your own fake class to unit test with. For instance, we use Moq where I work and your unit test example would look like this:

Here is an example of test with mocha and chai. We also need sinon to stub the http library.

http://sinonjs.org/releases/v1.17.7/stubs/

// test.js

const chai = require('chai');
const expect = chai.expect;
const sinon = require('sinon');
const http = require('http');

const someRequest = require('./index');

describe('some request test', function() {
  let httpGetStub;

  beforeEach(function() {
    httpGetStub = sinon.stub(http, 'get'); // stub http so we can change the response
  });

  afterEach(function() {
    httpGetStub.restore();
  });

  it('responses with success message', function() {
    httpGetStub.yields({ headers: { 'content-type': 200 }}); // use yields for callback based function like http.get
    return someRequest().then(res => { 
      expect(res).to.equal('Connected to Google');      
    });
  });

  it('rejects with error message', function() {
    httpGetStub.yields({ headers: { 'content-type': 400 }});
    return someRequest().catch(err => { 
      expect(err.message).to.equal('Failed to connect to Google');      
    });
  });
})

Hope it helps.

How to unit test NodeJS HTTP requests?, When unit testing, you don't want HTTP requests to go out and affect the result. Instead you create a fake request – a test double – to replace the  You have a class that depends on HttpClient (or IHttpClientFactory for that matter), and want to unit test that. Since you want a unit test and not an integration test, it should not call a real http endpoint. You decide to mock out your dependency on HttpClient, and soon thereafter you got stuck. After googling ‘How to mock HttpClient’ you landed on this post.

Testing with HTTP Requests - via @codeship, You probably even write unit tests and measure the code coverage of your business logic. Congrats! However, at that layer, you are only writing  Angular’s new HttpClient has a testing module, HttpClientTestingModule, that makes it easy to unit test HTTP requests.In this short post we’ll go over how to setup a simple unit test for an http GET request using that module, and in turn it should help demonstrate the capabilities of that new testing module.

Unit testing HTTP requests, I really rather think you have the right idea with the interface and your real class. I do heartily endorse your use of readonly which doesn't get a lot of exposure. Written a simple Node.js application that makes a HTTP request to an external endpoint. Write tests for the application; Mock the requests in the test. Setting Up The Project. To get started, create a simple Node.js application by creating an empty folder and running npm init. mkdir nock-tests cd nock-tests npm init Installing the packages

How to write unit tests for Angular code that uses the HttpClient?, Using that module, one can fully (unit)test a component or a service without using an actual server implementation to handle HTTP requests from the Angular  We inject a private variable of the HttpClient (Angular module to perform HTTP requests) into our constructor. Unlike in the tests, where we do not really perform real HTTP requests, thanks to the

Comments
  • How about mocking http.get ?
  • The purpose is to not be reliant on a network consistency to validate unit tests. The inverse(?) of this is integration testing.
  • Thanks @aurelienshz. This is the part that confuses me a little. What about if the sever is unreachable how does a mock help there? Is that an integration test for that?
  • @zero298 exactly, that's why I'm suggesting to mock http.get with a stub, so that he doesn't rely on whether Google responds with success or error to check the behaviour of the module under test.
  • Also @BugHunterUK, be careful that resp.headers['content-type'] is not the status of your response. You're probably looking for resp.status there.