У меня определен следующий объект TypeScript:
// HttpClient.ts
export type HttpResponse<T> = Response & {
data?: T;
}
async function get<T>(url: string, args: RequestInit = {}): Promise<HttpResponse<T>> {
return fetchRequest<T>(url, {...args, method: 'get'}) // fetchRequest returns value of type Promise<HttpResponse<T>>
}
export default {get} // default export represents an HttpClient object
У меня также есть другой файл getFeatureFlag.ts
, который использует этот HttpClient
в своей реализации:
// getFeatureFlag.ts
import HttpClient from '../httpClient'
export type FetchResponse<T = any, E = any> = {
data: Nullable<T>;
error: Nullable<E>;
}
export type FeatureFlag = {
toggleActive: boolean; // true/false denotes show/hide feature
}
export async function getFeatureFlag(flagName: string): Promise<FetchResponse<boolean, string>> {
const response = await HttpClient.get<FeatureFlag>(`/v1/toggles/${flagName}/`)
// ... rest of the implementation ...
}
I Я в процессе написания модульных тестов (с использованием Jest) для этого файла под getFeatureFlag.test.ts
, и у меня есть следующий фрагмент в нем:
// getFeatureFlag.test.ts
import HttpClient, {HttpResponse} from '../httpClient'
import {getFeatureFlag, FLAG_STORE, FeatureFlag} from '../index'
describe('getFeatureFlag', () => {
beforeEach(async () => {
// vv === THIS LINE IS WHAT THIS POST IS ABOUT === vv
jest.spyOn<HttpResponse<FeatureFlag>, 'get'>(HttpClient, 'get').mockImplementationOnce(() => ({
ok: true,
data: {
toggleActive: true,
},
}))
result = await getFeatureFlag(flagName)
})
it('then perform api request for feature flag data', () => {
expect(HttpClient.get).toHaveBeenCalledWith('/v1/toggles/featureFlag/')
})
})
Из файла определений @types/jest
, spyOn
функция определяется следующим образом:
function spyOn<T extends {}, M extends FunctionPropertyNames<Required<T>>>(
object: T,
method: M
): Required<T>[M] extends (...args: any[]) => any
? SpyInstance<ReturnType<Required<T>[M]>, ArgsType<Required<T>[M]>>
: never;
Мне очень трудно заставить компилятор TypeScript правильно читать приведенный ниже фрагмент без проблем.
jest.spyOn<HttpResponse<FeatureFlag>, 'get'>(HttpClient, 'get').mockImplementationOnce(() => ({
ok: true,
data: {
toggleActive: true,
},
}))
С указанной выше настройкой , компилятор сообщает мне, что get
не удовлетворяет ограничению never
, и я не понимаю, как решить здесь проблему ввода, чтобы мой тест был написан / запущен правильно. Другая вещь, которую я здесь пытаюсь сделать, - это вернуть только Partial
из HttpResponse
, потому что я, очевидно, не хочу заполнять все поля в моем модульном тесте, когда они не нужны.
Кто-нибудь смог правильно применить jest.spyOn
с дженериками, чтобы решить эту проблему?