简体   繁体   中英

Mocking with Jest + Supertest in Typescript

I am writing a mock test case with jest in typescript & trying to mock API calls with supertest, but unable to get a mocked response in return, as I'm using Axios on the login function & even tried to mock the Axios call but got no luck.

Here's my code :

auth.controller.ts

import { AxiosService } from "helpers";

export class AuthController {
    constructor() {
       ...
      // Some logic is written here
      this.init()
    }

    public init() {
       // prepared an route for login
       router.post('/api/auth/login', this.login);
    }
  
    login = async function (req: Request, res: Response): Promise<void> {
        // Preparing config for axios call with some logic
        ...

        // created a service for Axios call to some third party.
        AxiosService.call(req, res, config, "login");
    }
  }
    
    

auth.test.ts

import { AuthController } from "../../modules/auth/auth.controller";
jest.mock("../../modules/auth/auth.controller");

beforeAll(async () => {
  const auth = new AuthController();
  mockLogin = jest.spyOn(auth, "login");
});

afterAll(async () => {
  server.stop();
});

test("should give login response", async () => {
    mockLogin.mockImplementation(() => {
      return Promise.resolve({ Success: true, body: "Login" });
    });

      const response = await request(server.app)
        .post("/api/auth/login")
        .send(requestBody)
        .expect(200);

      response.body // Getting the server response instead of mocked one
})
    
    

Tried with this code too, but no luck over there :

jest.mock('../../modules/auth/auth.controller', () => {
  return { 
    AuthController: jest.fn().mockImplementation(() => {
          return {
              login: jest.fn()
          }   
      })
  }
})
            
    

Here's my AxiosService class looks like :

export class AxiosService {

  public static async call(...):Promise<void> { 
    try { 
       const { data } = await axios(...);

       res.status(200).json(data);
    } catch(err) {
       res.status(400).send(err);
     }
  
  }

}

Tried to mock AxiosService call method with the following line :

jest.mock('../../helpers/AxiosService', () => {
  return jest.fn().mockImplementation(() => {
    return { call: () => { return {success:true, data:'mock'}} }
  })
})

However, after mocking the Axios call, I'm getting Async callback was not invoked within the 10000 (which I've given) ms timeout specified by jest.setTimeout

Anyone can help that would be great for me, as I'm new to the mocking concept so maybe I'm missing something here.

Thanks in advance

A proper testing strategy that every unit but tested one needs to be mocked.

A timeout happens because Supertest waits for server response and there's none in case of mocked AxiosService , so it needs be mocked like:

...
return { call: (req, res) => { res.status(200).json({success:true, data:'mock'}); }

In this case the test can either mock controller class with mocked service class, or test them together with mocked Axios. Since AuthController doesn't do much alone (AuthController and AxiosService are abstractions over simple Express handler), it can be:

jest.mock('axios', () => jest.fn()) // at top level
...
axios.mockResolvedValue({ data: ... });
const response = await request(server.app)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM