我是Jest的Node.js单元测试的新手,并且还在学习中。我想知道单元测试调用API的函数的正确方法是什么?目前,我正在使用跨取库进行API调用。我想实现有效负载验证,API调用上的2xx和5xx API响应的单元测试。
这是我的代码:
export const myFunction = (payload: any) => {
if (_.isNull(payload) || _.isUndefined(payload)) {
throw new Error('payload is required')
}
httpFetch('http://localhost/api/send', { method: 'POST' }, { 'content-type': 'application/json', Authorization: 'Bearer 12ABC'})
.then((resp) => {
// ...return 2xx
})
.catch((e) => {
// ...return 5xx
})
}
答案 0 :(得分:0)
有两种方法可以做到这一点:
httpFetch = jest.fn(()=>Promise.resolve("provide-dummy-response-payload"));
httpFetch = jest.fn(()=>Promise.reject("provide-dummy-error-payload"));
现在,您可以在类似的测试中使用该模拟了:
// pseudo code
it("makes the api call successfully",async ()=>{
httpFetch = jest.fn(()=>Promise.resolve("provide-dummy-response-payload"));
const result = await myFunction("random-payload");
// make assertions about the result here
});
it("fails the api call",async ()=>{
httpFetch = jest.fn(()=>Promise.reject("provide-dummy-error-payload"));
const error = await myFunction("random-payload");
// make assertions about error here
});
在这种情况下,您将需要知道如何使API调用失败或失败。
因此,如果有效载荷不包含某个属性或属性类型不正确,您的API可能会失败。
这种方法取决于您提供给函数的有效载荷。
答案 1 :(得分:0)
广泛地有两种(不是互斥的)单元测试*这样的功能:
隔离测试,用test doubles替换协作者:
import httpFetch from "wherever";
import myFunction from "somewhere";
jest.mock("wherever");
describe("myFunction", () => {
it("calls httpFetch", async () => {
httpFetch.mockResolvedValue();
await myFunction({});
expect(httpFetch).toHaveBeenCalledWith(
"http://localhost/api/send",
{ method: "POST" },
{ "Content-Type": "application/json", Authorization: "Bearer 12ABC" }
);
});
});
这是“最简单”的方法,但是现在您已经连接到httpFetch
接口,这违反了规则“不要嘲笑您不拥有的东西” -如果该库的界面在某个时候发生了变化,这些测试不会告诉您。
集成测试,使用Nock之类的东西检查传输层发生的情况:
import nock from "nock";
import myFunction from "somewhere";
describe("myFunction", async () => {
it("makes the right request", () => {
const scope = nock("http://localhost/api", {
reqheaders: {
"Content-Type": "application/json",
Authorization: "Bearer 12ABC",
},
})
.post("/send")
.reply(201);
await myFunction({});
scope.done();
});
});
这需要更多的设置,但是意味着您与httpFetch
界面的耦合更少-例如,您可以升级该库或切换到另一个库,但仍然可以确信一切正常。
还有其他方法可以与特定库的接口分离;例如,您可以围绕它编写一个 facade 并对其进行模拟。但是您仍然想知道正在发出正确的请求,并且出于与以前相同的原因,您不应该针对库的测试倍数来测试外观。
您可能还会进行更高级别的测试,例如E2E针对真实的后端进行测试,或针对其后端进行合约测试;这将影响您希望如何平衡较低级别测试的数量和类型。总体而言,这些选项如下所示:
System: [Service] -> [Library] -> [HTTP] -> [Backend]
Isolated: |<----->| -> (Test Double)
Integration: |<------------------>| -> (Nock)
Contract: |<---------------------------->| -> (Stub)
E2E: |<----------------------------------------->|
请记住,目标(或one of them)是要确保您正在编写的代码能够正常工作,如果情况不再如此,您将以有助于您解决问题的方式迅速找到答案。
* 围绕“单元测试”的内容有很多想法。考虑到速度,独立性和并行性的原理,我在此上下文中使用的定义是:实际上没有发出网络请求的测试。