在 Typescript 中使用 Jest + Supertest 进行模拟
Mocking with Jest + Supertest in Typescript
我正在用 typescript 中的 jest 编写一个模拟测试用例并尝试用 supertest 模拟 API 调用,但无法在 return 中获得模拟响应,因为我在登录功能甚至试图模拟 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 class 看起来像:
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 调用之后,我得到 异步回调未在 jest.setTimeout[=42= 指定的 10000(我给出的)毫秒超时内调用]
任何人都可以提供帮助,这对我来说非常好,因为我是模拟概念的新手,所以我可能在这里遗漏了一些东西。
提前致谢
一个适当的测试策略,除了测试一个单元之外的每个单元都需要被模拟。
发生超时是因为 Supertest 等待服务器响应并且在模拟 AxiosService
的情况下有 none,因此需要像这样模拟:
...
return { call: (req, res) => { res.status(200).json({success:true, data:'mock'}); }
在这种情况下,测试可以模拟控制器 class 和模拟服务 class,或者将它们与模拟 Axios 一起测试。由于 AuthController 单独做的事情不多(AuthController 和 AxiosService 是对简单 Express 处理程序的抽象),它可以是:
jest.mock('axios', () => jest.fn()) // at top level
...
axios.mockResolvedValue({ data: ... });
const response = await request(server.app)
我正在用 typescript 中的 jest 编写一个模拟测试用例并尝试用 supertest 模拟 API 调用,但无法在 return 中获得模拟响应,因为我在登录功能甚至试图模拟 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 class 看起来像:
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 调用之后,我得到 异步回调未在 jest.setTimeout[=42= 指定的 10000(我给出的)毫秒超时内调用]
任何人都可以提供帮助,这对我来说非常好,因为我是模拟概念的新手,所以我可能在这里遗漏了一些东西。
提前致谢
一个适当的测试策略,除了测试一个单元之外的每个单元都需要被模拟。
发生超时是因为 Supertest 等待服务器响应并且在模拟 AxiosService
的情况下有 none,因此需要像这样模拟:
...
return { call: (req, res) => { res.status(200).json({success:true, data:'mock'}); }
在这种情况下,测试可以模拟控制器 class 和模拟服务 class,或者将它们与模拟 Axios 一起测试。由于 AuthController 单独做的事情不多(AuthController 和 AxiosService 是对简单 Express 处理程序的抽象),它可以是:
jest.mock('axios', () => jest.fn()) // at top level
...
axios.mockResolvedValue({ data: ... });
const response = await request(server.app)