[英]How to allow partial TypeScript types when mocking functions - Jest, TypeScript
I have a function which I would like to mock for testing purposes in TypeScript.我有一个 function,我想在 TypeScript 中模拟它以进行测试。 In my tests, all I care about are the
json
and the status
.在我的测试中,我只关心
json
和status
。 However, when using Jest's jest.spyOn
the type of my mocked function is set to return a http Response
type.但是,当使用 Jest 的 jest.spyOn 时,我模拟的
jest.spyOn
的类型设置为返回 http Response
类型。 This is awkward as it means I have to manually go and implement a bunch of functions and properties that are irrelevant and arbitrary.这很尴尬,因为这意味着我必须手动 go 并实现一堆不相关且任意的功能和属性。
I suspect there is some way to use a partial type here to allow better and more useful mocking by overriding the return type to only that I care about.我怀疑这里有某种方法可以使用部分类型,通过将返回类型覆盖为我关心的类型,从而实现更好、更有用的 mocking。 How would I go about doing this?
我将如何 go 这样做?
export function mockApi(json: object, status: number): void {
jest.spyOn(
myApiModule,
'methodWhichReturnsAResponse'
).mockImplementation(() =>
Promise.resolve({
json: () => Promise.resolve(json),
status,
// Below here is to appease jest types (not needed for
// testing purposes at the time of writing)
headers: {
has: (name: string) => true,
// get, set, etc...
},
ok: true,
redirected: false,
// and about 10 other properties which exist on the Response type
// ...
}),
);
}
You can use as
...您可以
as
...
export function mockApi(json: object, status: number): void {
jest.spyOn(
myApiModule,
'methodWhichReturnsAResponse'
).mockImplementation(() =>
Promise.resolve({
json: () => Promise.resolve(json),
status
} as http.Response), // <-- here
);
}
The as
keyword, used for typecasting, when used to convert a literal to type X, will allow you to define it only partially, but you still have type-checking because you cannot define props that don't exist. as
关键字,用于类型转换,当用于将文字转换为 X 类型时,将允许您仅部分定义它,但您仍然需要进行类型检查,因为您无法定义不存在的道具。
Example:例子:
type X {
a: number
b: number
}
const x = { a: 2 } as X // OK
const y = { a: 3, c: 2 } as X // NOT OK, because c does not exist in X
I found a solution using the unknown
type.我找到了使用
unknown
类型的解决方案。
After trying and failing to use as
to typecast immediately, I first cast the promise to unknown
and then cast this value to the desired Response
type like so:在尝试并未能立即使用
as
进行类型转换后,我首先将 promise 转换为unknown
,然后将此值转换为所需的Response
类型,如下所示:
// ...
.mockImplementation(() => {
const httpResponsePromise = Promise.resolve({
json: () => Promise.resolve(json),
status,
}) as unknown;
return httpResponsePromise as Promise<Response>;
});
I wrote the utility below which gives my codebase a partiallyMock<T>({})
call having property autocompletion for any type...我在下面编写了实用程序,它为我的代码库提供了一个
partiallyMock<T>({})
调用,该调用具有任何类型的属性自动完成......
/** Simple mocking inspired by https://www.npmjs.com/package/jest-mock-extended
* which has mockDeep<T>() for excellent autocompletion support but had other issues. */
/* atomic values (not made Partial when mocking) */
type Atomic = boolean | string | number | symbol | Date;
/** Mocks an indexed type (e.g. Object or Array), making it recursively Partial - note question mark */
type PartialMockIndexed<T> = {
[P in keyof T]?: PartialMock<T[P]>;
};
/** Mock any T */
export type PartialMock<T> = T extends Atomic ? T : PartialMockIndexed<T>;
/** Utility method for autocompleting a PartialMock<T> and returning it as a T */
export function partiallyMock<T>(mock: PartialMock<T>) {
return mock as T;
}
/** Window is a special object, needs special mocking */
export function mockWindow(windowMock: PartialMock<typeof window>) {
const origWindow = window;
globalThis.window = Object.create(window);
for (const [key, value] of Object.entries(windowMock)) {
Object.defineProperty(globalThis.window, key, { value });
}
const unmockWindow = (globalThis.window = origWindow);
return unmockWindow;
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.