Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Best Way to Test Promises in Jest

Unless I'm misunderstanding something, the resolves and rejects (https://facebook.github.io/jest/docs/expect.html#resolves) won't be available until vNext. What is the recommended way now/in the meantime to test promises with Jest? Is it just putting expects in the thens and catches?

For example:

describe('Fetching', () => {
    const filters = {
        startDate: '2015-09-01'
    };
    const api = new TestApiTransport();

    it('should reject if no startdate is given', () => {
        MyService.fetch().catch(e => expect(e).toBeTruthy()); // see rejects/resolves in v20+
    });            

    it('should return expected data', () => {
        MyService.fetch(filters, null, api).then(serviceObjects => {
            expect(serviceObjects).toHaveLength(2);
        }).catch(e => console.log(e));
    });            
});

UPDATE 15 June 2019: Not too long after I posted this question, Jest started supporting this out of the box. I changed the accepted answer below to reflect the currently best way to do this.

UPDATE 8 Dec 2021: At some point Jest started supporting async/await. So while other methods noted work, I've taken to simply (for most cases) using something like:

it('should do something', async () => {
    const expected = true; 
    expect(await funcToTest()).toEqual(expected);
});

As with most cases, async/await is much more readable than alternatives. The only case I use resolves or rejects now is for simple cases like:

it('should not throw when doing something', async () => {
    await expect(funcToTest()).resolves.not.toThrow();
});

it('should throw when something is wrong', async () => {
    await expect(funcToTest()).rejects.toThrow();
});
like image 418
Ambrose Little Avatar asked Mar 27 '17 03:03

Ambrose Little


People also ask

How do I resolve a promise in Jest?

You can also use the . resolves matcher in your expect statement, and Jest will wait for that promise to resolve. If the promise is rejected, the test will automatically fail. return expect(fetchData()).

Is Jest enough for testing?

Jest is a JavaScript test runner that lets you access the DOM via jsdom . While jsdom is only an approximation of how the browser works, it is often good enough for testing React components.

Is Jest good for API testing?

Jest is great for validation because it comes bundled with tools that make writing tests more manageable. While Jest is most often used for simple API testing scenarios and assertions, it can also be used for testing complex data structures.


Video Answer


4 Answers

Nowadays you can write it in this way as well: docs

describe('Fetching', () => {
    const filters = {
        startDate: '2015-09-01'
    };
    const api = new TestApiTransport(); 

 it('should reject if no startdate is given', () => {
   expect.assertions(1);
   return expect(MyService.fetch()).rejects.toEqual({
     error: 'Your code message',
   });
 });          


 it('should return expected data', () => {
   expect.assertions(1);
   return expect(MyService.fetch(filters, null, api)).resolves.toEqual(extectedObjectFromApi);
 });            
});

Update (06.01.2019)

Agree that the accepted answer doesn't work correctly as line expect.assertions(1); does all the magic. Link to docs

expect.assertions(number) verifies that a certain number of assertions are called during a test. This is often useful when testing asynchronous code, in order to make sure that assertions in a callback actually got called.

So putting this line at the top will control that the specific number of assertions are made by the time when the test is run.

like image 57
Yevhenii Herasymchuk Avatar answered Sep 30 '22 19:09

Yevhenii Herasymchuk


Either return a promise and expect in the resolve or catch

describe('Fetching', () = > {
  const filters = {
    startDate: '2015-09-01'
  };
  const api = new TestApiTransport();
  it('should reject if no startdate is given', () = > {
    return MyService.fetch()
      .catch (e => expect(e).toBeTruthy()); // see rejects/resolves in v20+
  });
  it('should return expected data', () = > {
    return MyService.fetch(filters, null, api)
      .then(serviceObjects => {
        expect(serviceObjects).toHaveLength(2);
      })
  });
});

or using async/await

describe('Fetching', () = > {
  const filters = {
    startDate: '2015-09-01'
  };
  const api = new TestApiTransport();
  it('should reject if no startdate is given', async() = > {
    try {
      const r = await MyService.fetch()
    } catch (e) {
      expect(e).toBeTruthy()
    }
  });
  it('should return expected data', async() = > {
    const serviceObjects = await MyService.fetch(filters, null, api)
    expect(serviceObjects).toHaveLength(2);
  });
});
like image 27
Andreas Köberle Avatar answered Sep 30 '22 19:09

Andreas Köberle


I was able to test JEST with AXIOS for HTTP REST calls like this.

it('has an API worth testing', async () => {
  let httpResult = null;
  await callThefunctionThatReturnsPromiseToMakeTheAxiosApiCall()
    .then(function(result) {httpResult=result;})
    .catch(function(err) {httpResult=err;});
  expect(httpResult.data.myData).toBe("myExpectedValue");
});

or

it('has an API worth testing', async () => {
  let httpResult = await callThefunctionThatReturnsPromiseToMakeTheAxiosApiCall();
  expect(httpResult.data.myData).toBe("myExpectedValue");
});
like image 30
Sagan Avatar answered Sep 30 '22 19:09

Sagan


For additional Jest matchers maintained by the Jest Community check out jest-extended.

https://jestjs.io/docs/expect

Using jest-extended you can expect your promise toResolve() or toReject(). Then you can expect the result or the error to match something. For example:

test('OK status', async () => {
  const request = fetch(...)
  await expect(request).toResolve() // First, make sure it resolves
  const data = await request
  expect(data).toEqual(...) // Then test the result
})
test('ERROR status', async () => {
  const request = fetch(...)
  await expect(request).toReject() // First, make sure it rejects
  await request.catch((error) => expect(error).toBe('...')) // Then test the error
})
like image 37
Mir-Ismaili Avatar answered Sep 30 '22 21:09

Mir-Ismaili