2017-08-22 13 views
7

Trong ứng dụng tạo phản ứng của tôi, tôi đang cố thử nghiệm một thành phần thực hiện nhiều lần setState khi được gắn kết.Làm thế nào để đợi cho đến khi thành phần React hoàn tất cập nhật trong Jest và/hoặc Enzyme?

class MyComponent extends React.Component { 

    state = { 
    a: undefined, 
    b: undefined, 
    c: undefined, 
    }; 

    fetchA() { 
    // returns a promise 
    } 

    fetchB() { 
    // returns a promise 
    } 

    fetchC() { 
    // returns a promise 
    } 

    async componentDidMount() { 
    const a = await fetchA(); 
    this.setState({ a }); 
    } 

    async componentDidUpdate(prevProps, prevState) { 
    if (prevState.a !== this.state.a) { 
     const [b, c] = await Promise.all([ 
     this.fetchB(a); 
     this.fetchC(a); 
     ]); 
     this.setState({ b, c }); 
    } 
    } 

    ... 

} 

Trong thử nghiệm của tôi, tôi làm điều gì đó như thế này, cố gắng để cho các setState trong componentDidUpdate để kết thúc trước khi đưa ra khẳng định.

import { mount } from 'enzyme'; 

describe('MyComponent',() => { 

    const fakeA = Promise.resolve('a'); 
    const fakeB = Promise.resolve('b'); 
    const fakeC = Promise.resolve('c'); 

    MyComponent.prototype.fetchA = jest.fn(() => fakeA); 
    MyComponent.prototype.fetchB = jest.fn(() => fakeB); 
    MyComponent.prototype.fetchC = jest.fn(() => fakeC); 

    it('sets needed state', async() => { 
    const wrapper = mount(<MyComponent />); 
    await Promise.all([ fakeA, fakeB, fakeC ]); 
    expect(wrapper.state()).toEqual({ 
     a: 'a', 
     b: 'b', 
     c: 'c', 
    }); 
    }); 

}); 

Đây là một phần thú vị: thử nghiệm của tôi ở trên sẽ thất bại vì setState cuộc gọi cuối cùng (trong componentDidUpdate) đã không hoàn thành khi khẳng định được thực hiện. Vào thời điểm đó, state.a được đặt, nhưng state.bstate.c chưa được đặt.

Cách duy nhất tôi có thể làm cho nó hoạt động là bằng cách nêm await Promise.resolve(null) ngay trước khi xác nhận để cung cấp dấu kiểm/chu kỳ bổ sung cuối cùng để hoàn thành. Điều này có vẻ quá hacky.

Một điều khác mà tôi đã thử là bao gồm xác nhận trong setImmediate(), hoạt động tốt miễn là xác nhận chuyển. Nếu nó không thành công, nó sẽ chấm dứt toàn bộ bài kiểm tra vì lỗi vô ích.

Có ai đã khắc phục sự cố này không?

+0

Nó có hoạt động nếu bạn thay thế câu lệnh 'Promise.all' bằng hai câu lệnh, như' const b = await this.fetchB (a) ... '? Hoặc có thể chế nhạo 'Promise.all'. Tôi đoán là, vấn đề đó là lời hứa mà bạn tạo ra ở đó, điều đó không hề biết. –

+0

Bạn đang đề cập đến 'Promise.all' trong thành phần hoặc trong thử nghiệm? Nếu nó trong bài kiểm tra, tôi chắc chắn rằng tôi xác nhận rằng jest chờ đợi cho cả ba để kết thúc. Tuy nhiên, bài kiểm tra sẽ tiếp tục ngay sau khi 3 lời hứa kết thúc, mà không cần đợi 'setState' cuối cùng trong' componentDidUpdate' để kết thúc. Bất kể, tôi sẽ cố gắng chơi với những gì bạn nói. – vleong

+0

Bạn đã giải quyết được sự cố này chưa? – prime

Trả lời

2

Đây là cách tôi đã giải quyết. Hy vọng rằng sẽ giúp một ai đó.

import { mount } from 'enzyme'; 

describe('MyComponent',() => { 

    const fakeA = Promise.resolve('a'); 
    const fakeB = Promise.resolve('b'); 
    const fakeC = Promise.resolve('c'); 

    MyComponent.prototype.fetchA = jest.fn(() => fakeA); 
    MyComponent.prototype.fetchB = jest.fn(() => fakeB); 
    MyComponent.prototype.fetchC = jest.fn(() => fakeC); 

    it('sets needed state', async (done) => { 
    const wrapper = mount(<MyComponent />); 
    await Promise.all([ fakeA, fakeB, fakeC ]); 

    setImmediate(() => { 
     // Without the try catch, failed expect will cause the 
     // whole test to crash out. 
     try { 
     expect(wrapper.state()).toEqual({ 
      a: 'a', 
      b: 'b', 
      c: 'c', 
     }); 
     } catch(error) { 
     done.fail(error); 
     } 
     done(); 

    }); 

}); 
Các vấn đề liên quan