ค้นหาเว็บไซต์

jestjs - การจำลองด้วย Jest + Supertest ใน Typescript


ฉันกำลังเขียนกรณีทดสอบจำลองด้วย jest ใน typescript และพยายามจำลองการเรียก API ด้วย supertest แต่ไม่สามารถได้รับผลตอบกลับที่จำลองไว้ เนื่องจากฉันกำลังใช้ Axios ในฟังก์ชันล็อกอิน และแม้แต่ลองจำลองการเรียก Axios ก็ไม่สำเร็จ

นี่คือโค้ดของฉัน:

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

ลองกับโค้ดนี้แล้วเช่นกัน แต่ก็ไม่สำเร็จที่นั่น :

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

นี่คือลักษณะของคลาส AxiosService ของฉัน:

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

}

พยายามจำลองเมธอดการเรียกของ AxiosService ด้วยบรรทัดต่อไปนี้ :

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

อย่างไรก็ตาม หลังจากที่เลียนแบบการเรียกใช้งาน Axios แล้ว ฉันได้รับ Async callback ไม่ถูกเรียกใช้งานภายใน 10000 มิลลิวินาที (ซึ่งฉันกำหนด) ที่ระบุโดย jest.setTimeout

ใครก็ตามที่สามารถช่วยได้นั้นจะยอดเยี่ยมสำหรับฉัน เพราะฉันเป็นมือใหม่เกี่ยวกับแนวคิดการล้อเลียน ดังนั้นบางทีฉันอาจพลาดอะไรบางอย่างไป

ขอบคุณล่วงหน้า

คำตอบ #1

กลยุทธ์การทดสอบที่เหมาะสมคือทุกหน่วยที่ไม่ได้ทดสอบต้องถูกจำลอง

เกิดการหมดเวลาการรอเพราะ Supertest รอการตอบกลับจากเซิร์ฟเวอร์และไม่มีการตอบกลับในกรณีของ AxiosService ที่ถูกจำลอง ดังนั้นจึงจำเป็นต้องจำลองแบบนี้:

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

ในกรณีนี้ การทดสอบสามารถทำได้ทั้งการจำลองคลาสคอนโทรลเลอร์ด้วยคลาสเซอร์วิสที่จำลองไว้ หรือทดสอบพวกมันร่วมกันโดยใช้ Axios ที่จำลองไว้ เนื่องจาก AuthController ไม่ได้ทำอะไรมากเอง (AuthController และ AxiosService เป็นการสร้างนามธรรมเหนือตัวจัดการ Express ง่ายๆ) มันสามารถเป็นได้:

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

บทความที่เกี่ยวข้อง