Alex's Slip-box

These are my org-mode notes in sort of Zettelkasten style

Mocking fetch in a jsdom node environment

# The problem

Node.JS environments don’t have fetch. Ok, so what, I’ll just use node-fetch, right? Yes, but when I was unit testing a VueJS app, this didn’t work. I think it was because of an incompatibility with jsdom. My colleagues and I were getting this error:

TypeError: Cannot set property 'Headers' of undefined
at Object../node_modules/node-fetch/browser.js (/app/public/v2/js/webpack:/node_modules/node-fetch/browser.js:23:1)

We bailed on using node-fetch and opted to just mock the fetch instead.

# Mocking Fetch in Mocha Tests

  • This example uses Sinon.JS.
  • fetch didn’t exist on global which typescript was complaining about. Using an any type assertion got around this.
  • The json property on a fetch response is actually a function that returns a ~Promise.
interface FakeResponse {
  readonly ok: boolean;
  readonly status: number;
  json(): Promise<any>;
}

describe('something', () => {
  const data = { foo: 'bar' }
  const fakeJson = sinon.fake.resolves(data);
  const fakeResponse: FakeResponse = { ok: true, status: 200, json: fakeJson };
  const fetchStub = sinon.stub();
  fetchStub.withArgs('https://example.com/posts.json').resolves(fakeResponse);

  beforeEach(() =>{
    (<any>global).fetch = fakeFetch;
  })

  afterEach(() => {
    delete (<any>global).fetch;
  })

  it('gets the data', (done) => {
    const someApi = new SomeApi();
    expect(someApi.someMethodThatUsesFetch())
      .to.eventually.deep.equal(data)
      .notify(done);
  })
})