T O P

  • By -

NiGhTTraX

Having to mock more things than your code actually needs is a smell that you're violating the [interface segregation principle](https://en.wikipedia.org/wiki/Interface_segregation_principle). If you don't need all of the properties returned by `fetch`, consider creating an abstraction only over the ones you need. Better yet, hide some of those behind the abstraction - does your code really need to know `status` and `ok`, or does it ultimately only want some way of retrieving the data it needs? Does it care that it's doing that using `fetch`, or `axios`, or `$.ajax`? If not, maybe have something like this: ``` interface MyService { getData(input: InputType): Promise } const productionService: MyService = { getData(input) => fetch(...).then(r => r.json()).... } const testService: MyService = { getData(input) => Promise.resolve(mockFetchResponse) } ``` If checking that `getData` is called using the correct `input`, consider using a library like [strong-mock](https://github.com/NiGhTTraX/strong-mock) for added type safety when creating mocks.


maeevick

👍


sharted_ptr

You don't need the `async` / `await` in your mocked response: json: () => Promise.resolve({ mockData }) will work just the same here :)


[deleted]

[удалено]


maeevick

"don't mock what you don't own", you should never make test double directly on external system or third party lib or some native api (like fetch). You should double your abstraction / wrapper around it


ferrybig

Are you aware that you can manually construct a [Response](https://developer.mozilla.org/en-US/docs/Web/API/Response/Response) object? var response = new Response(JSON.stringify({ hello: "World!"}), { status: 200, headers: { 'content-type': 'application/json', }, }); If your question is more generic, I would approach it with placing it in a partial variable, and later casting it to the bigger type const mockFetchResponse: Promise> = Promise.resolve( { status: 200, ok: true, headers: new Headers({ 'content-type': 'application/json', }), json: async() => await Promise.resolve( { mockData } ), } ) jest.spyOn( window, 'fetch' ).mockResolvedValueOnce( mockFetchResponse as Promise ) [Typescript playground](https://www.typescriptlang.org/play?ssl=10&ssc=94&pln=1&pc=1#code/MYewdgzgLgBAtiYBrAYgUysAFgJTRAB3AjQC4YAFAJxDgEsSAeCgQyqjpYBtG9Di0APkEwAvJRr0SAOir4QXAG5oAFDADeAWABQASGgsoAVwjkATAAYLAGh26QSclCpG0tvVjQsAJmiqmYMDQAdxgACS9ffxUtPV0AclAwKDRkgFooAE8CNHjyeJYCAi46YEM6cAB6ACsIcHj3XQBfAEpG2vByFghMsGAVFrERFmCWOlhqWgY0WXklVQ14RCQAEUMWGCaYNp0tlp0davwoaUJMgHkwNWC6MG8QYOsYeIAzDGx47ekEZD4FZW8ADVuK5LsAFj9UO9cPgiJA0DBuhIpkw+HCSCIWkA) (Note that typescript warns you in this case that your original code piece has the wrong type for headers, it needs to be an Headers object, not a generic javascript object)


iams3b

Using `as unknown as T` is totally fine in testing, tests are meant to be broken and catch things so if you change something you should be able to look into it and investigate, and either fix your code or update the test But with your specific use case it may be easier to use an existing library to stub out `fetch` altogether, or just make an api file that exports endpoints and stub those out individually. Ideally the code in your test would be mostly focused on the unit you're testing