myol
myol

Reputation: 9858

Create IncomingMessage test dummy in Jest

I am trying to write a unit test for a function that takes IncomingMessage as a parameter. I understand it is a stream but I am unsure how to create a basic test dummy as the stream causes my tests to timeout

: Timeout - Async callback was not invoked within the 5000 ms timeout specified by jest.setTimeout.Timeout - Async callback was not invoked within the 5000 ms timeout specified by jest.setTimeout.Error:

My class

import { IncomingMessage } from 'http';

export class MyClass
  example(request: IncomingMessage): void {
    console.log(request.get('hello?'))
  }
}

My test

it('test', () => {
  const myclass = new MyClass();

  const request = {
    get: () => 'hello!'
  } as unknown as IncomingMessage

  const response = myclass.example(request);

  expect(response).toEqual('hello!'); 
});

I assume I need to close the stream so how can I do that when casting a 'dummy' object to type IncomingMessage?

I tried using

const request = {
  get: () => 'hello'
} as unknown as IncomingMessage
request.setTimeout(1)

but then I get an error that the function is not found, which makes sense since the dummy is basically an empty object with only one mocked function

TypeError: request.setTimeout is not a function

In this case I assume I need to actually create a real IncomingMessage? But I cannot find much documentation or examples on how to do this

What is the best way to create a real IncomingMessage stream, close it quickly and have a mocked get method? I think I would then need to mock a socket?

Or what is the correct way to test my class and function in this case?

Upvotes: 3

Views: 3413

Answers (2)

B3none
B3none

Reputation: 409

If you're not using express and using the built in http library for node you can do the following:

Note: This will also work with express too

import httpMocks from 'node-mocks-http';
import handleRequest from '../../../handlers/request';

describe('incoming message mock', () => {
  it('working example', () => {
    const mockRequest = httpMocks.createRequest({
      method: 'POST',
      url: '/my-fantastic-endpoint',
      headers: {
        'content-type': 'application/json',
        'accept': 'application/json',
        'content-length': '1',
        'x-forwarded-for': '127.0.0.1',
      },
    });

    mockRequest.destroy = jest.fn();

    const mockResponse = httpMocks.createResponse();

    handleRequest(mockRequest, mockResponse);

    mockRequest.send({
      example: 'hello!',
    });

    console.log(mockResponse._getData());

    expect(true).toBe(true);
  });
});

Upvotes: 1

bhaginath
bhaginath

Reputation: 456

Basically you need to mock your request object that can be done with below snippet:

function _mock_req() {
    let req = {
        get: jest.fn(() => 'hello!'),
    };
    return req;
}

Once mocking is done invoke it in your test case, here I'm using beforeEach that will take care of the issue: openHandler- Async callback was not invoked.

describe('http test', () => {
    let req, res;
    const myclass = new MyClass();

    beforeEach((done) => {
        req = _mock_req();
        res = myclass.example(req);
        done();
    });

    it('class test', () => {
        expect(res).toEqual('hello!');
    });
});

You also need to return request from your class to test get passed. While executing test case your mocked request object will get return from MyClass

export class MyClass {
    example(request: IncomingMessage): void {
        console.log(request.get('hello?'));
        return request.get('hello?')
    }
}

Test case result:

enter image description here

Upvotes: 2

Related Questions