How to make Jest wait for all asynchronous code to complete execution before waiting for approval

I am writing an integration test for a React application, i.e. A test that tests many components together and I want to mock any calls to external services.

The problem is that the test seems to run before the asynchronous callback is executed, which will cause my tests to fail.

Anyway, around? Can I somehow wait for the asynchronous code call to finish?

Here is some bad pseudo code to illustrate my point.

I would like to verify that when I mount Parent, its child component renders the content returned from the external service that I will mock.

class Parent extends component
{
     render ()
     {
         <div>
            <Child />
         </div>
     }
}
class Child extends component
{
     DoStuff()
     {
         aThingThatReturnsAPromise().then((result) => {
           Store.Result = result
         })
     }

    render()
    {
       DoStuff()
       return(<div>{Store.Result}</div>)


    }
}
function aThingThatReturnsAPromise()
{
     return new Promise(resolve =>{
          eternalService.doSomething(function callback(result) {
               resolve(result)
          }
    }

}

, , , .

jest.mock('eternalService', () => {
    return jest.fn(() => {
        return { doSomething: jest.fn((cb) => cb('fakeReturnValue');
    });
});

describe('When rendering Parent', () => {
    var parent;

    beforeAll(() => {
        parent = mount(<Parent />)
    });

    it('should display Child with response of the service', () => {
        expect(parent.html()).toMatch('fakeReturnValue')
    });
});

? , zonejs, React?

+20
5

, :

const flushPromises = () => new Promise(setImmediate);
Hide result

, setImmediate ( , ). , . :

, , .

, async/await:

it('is an example using flushPromises', async () => {
    const wrapper = mount(<App/>);
    await flushPromises();
    wrapper.update(); // In my experience, Enzyme didn't always facilitate component updates based on state changes resulting from Promises -- hence this forced re-render

    // make assertions 
});
Hide result

, .

+11

React, , .

, , beforeAll() @done . . :

let setupComplete;
jest.mock('eternalService', () => {
    return jest.fn(() => {
        return { doSomething: jest.fn((cb) => { cb('fakeReturnValue'); setupComplete(); }) };
});
.
.
.
    beforeAll(done => {
        parent = mount(<Parent />)
        setupComplete = done;
    });
});
Hide result

, Jest runAllTicks runAllImmediates.

+1

, React ( componentWillMount() componentDidMount(), . , . , !

describe('When rendering Parent', () => {
    it('should display Child with the response of the service', function(done) => {
        const parent = mount(<Parent />);
        expect(parent.html()).toMatch('fakeReturnValue');
        done();
    });
});
+1

JavaScript , JavaScript , . Jest , : http://jestjs.io/docs/en/asynchronous.html async/ , .

, . .

let parent
let eternalService = jest.fn(() => 'fakeReturnValue');

beforeEach(() => {
    parent = mount(<Parent />)
    parent.instance().externalService = externalService
})

describe('When rendering Parent', () => {
    it('should display Child with response of the service', () => {
        expect(parent.html()).toMatch('fakeReturnValue')
    });
});
Hide result
+1

aThingThatReturnsAPromise() , .

Since it aThingThatReturnsAPromise()returns a promise, you can use the asynchronous Jest testing functions. A gesture will wait for your promise, and you will be able to make your statements.

describe('When rendering Parent', () => {
    var parent;

    beforeAll(() => {
        parent = mount(<Parent />)
    });

    it('should display Child with response of the service', () => {
        expect.assertions(1);

        return aThingThatReturnsAPromise().then( () => {
            expect(parent.html()).toMatch('fakeReturnValue');
        });
    });
});

For more information, read how Jest handles test cases with promises in Jest Docs here.

+1
source

Source: https://habr.com/ru/post/1680037/


All Articles