sennett
sennett

Reputation: 8424

Jest assert promise resolved with object containing

Say I want to test a module that returns a Promise:

function myFunc () {
    return Promise.resolve({
        anArray: [1,2,3,4,5,6]
    })
}

Using Jest, how can I assert the length of the array contained in the object the promise resolves to?

describe('myFunc', () => {
  it('returns array of length 6', () => {
    expect.assertions(1)
    return expect(myFunc()).resolves // ... something here
  })
})

If it were synchronous, I would do something like:

let result = myFunc()
expect(result.anArray.length).toBe(6)

How does this work with Promises?

Upvotes: 2

Views: 3548

Answers (3)

Brian Adams
Brian Adams

Reputation: 45810

The easiest approach is to use .resolves like you were starting to do in your sample.

You just need to chain .toMatchObject to the result:

function myFunc () {
  return Promise.resolve({
      anArray: [1,2,3,4,5,6]
  })
}

describe('myFunc', () => {
  it('returns array of length 6', () => {
    expect(myFunc()).resolves.toMatchObject({ anArray: [1,2,3,4,5,6] });  // Success!
  })
})

This will assert that the object has at least the anArray property set to [1,2,3,4,5,6] (it can have other properties as well).

Note that PR 5364 makes it so resolves validates its arguments synchronously so you don't even have to return, await, or use done if you are using Jest >= v22.2.0.


Update

Sounds like the goal is to only assert on the length of the array.

For that you would need to get the result of the Promise (as has been described in the previous answers), then use .toHaveLength to assert the length of the anArray property:

describe('myFunc', () => {
  it('returns array of length 6', async () => {
    const result = await myFunc();
    expect(result.anArray).toHaveLength(6);  // Success!
  })
})

Upvotes: 2

Andreas Köberle
Andreas Köberle

Reputation: 110922

There are two ways either return the promise from the test and make the assertion in the then or make your test using async/await

describe('myFunc', () => {
  it('returns array of length 6', () => {
    expect.assertions(1)
    return expect(myFunc())
      .then(result =>  expect(result).toEqual([1,2,3,4,5,6]);)
  })
})

describe('myFunc',() => {
  it('returns array of length 6', async() => {
    const result = await expect(myFunc())
    expect(result).toEqual([1,2,3,4,5,6]);)
  })
})

The docs on this topic

Upvotes: 4

Sergeon
Sergeon

Reputation: 6788

A way to do this is to pass a done callback, to mark your test as asynchronous and force jest to wait until you call done():

describe('myFunc', () => {
  it('returns array of length 6', (done) => {
    expect.assertions(1)
    myFunc().then((values) => {
      expect(values).toEqual([1,2,3...]);
      done();
    });
  })
})

You can just return a Promise as well, without the need for done:

describe('myFunc', () => {
  it('returns array of length 6', () => {
    expect.assertions(1)
    return myFunc().then((values) => {
      expect(values).toEqual([1,2,3...]);
    });
  })
})

You can read more about this here.

Upvotes: 1

Related Questions