Как проверить функцию компонента, вызываемую при componentDidMount? - PullRequest
0 голосов
/ 06 августа 2020

У меня есть React JS компонент MyComponent, и я хотел бы протестировать следующий вариант использования:

Он должен вызывать updateSomething() при установке компонента

И я придумал следующий код:

Тестируемая система (SUT)

export class MyComponent extends React.Component<Props, State> {
    public componentDidMount() {
        console.log("componentDidMount"); // Debug purpose.
        this.fetchSomething()
            .then(() => {
                console.log("fetchSomething"); // Debug purpose.
                this.updateSomething();
            });
    }

    // These are public for simplicity
    public async fetchSomething(): Promise<any> { }
    public updateSomething() {
         console.log("updateSomething"); // Debug purpose.
    }
}

Тест

it("should update something, when on mount", () => {
    const props = { ...baseProps };
    sinon.stub(MyComponent.prototype, "fetchSomething").resolves();
    const spy = sinon.spy(MyComponent.prototype, "updateSomething");

    shallow(<MyComponent {...props} />);

    sinon.assert.calledOnce(spy);
});

Результат - тест не удалось с AssertError: expected updateSomething to be called once but was called 0 times, но все три console.log() напечатаны.

Насколько я понимаю, поскольку я хочу протестировать событие, когда оно установлено, мне нужно шпионить / заглушить его, прежде чем оно даже будет создано, поэтому я должен шпионить на MyComponent.Prototype. Кроме того, для fetchSomething() я должен заглушить вызов asyn c и сделать его .resolves(), чтобы он продолжался.

Но я не мог понять, как он может все еще console.log("updateSomething") без шпионажа .

Ответы [ 2 ]

0 голосов
/ 11 августа 2020

Согласно комментариям / ответу от этого сообщения , утверждение приходит до того, как были вызваны .updateSomething. Чтобы решить эту проблему, мне пришлось бы дождаться метода жизненного цикла componentDidMount.

Итак, фиксированная программа выглядит следующим образом:

// SUT

public async componentDidMount() {
    //...
    return this.fetchSomething()
        .then(() => {
            //...
        });
}

// Test

it("should update something, when on mount", () => {
    const props = { ...baseProps };

    // Disable lifecycle here to enable stub in between.
    const wrapper = shallow(<MyComponent {...props} />, { disableLifecycleMethods: true });

    sinon.stub(wrapper.instance(), "fetchSomething").resolves();
    const stub = sinon.stub(wrapper.instance(), "updateSomething");

    // Actually call component did mount.
    wrapper.instance().componentDidMount().then(() => {
         sinon.assert.calledOnce(stub);
    });
});
0 голосов
/ 06 августа 2020

Я не знаю о sinon и не знаю о ts, но с простыми js и jest это будет примерно так:

fetchSomething() = Promise.resolve();

Тогда в вашем тесте вам не придется издеваться над ним и просто использовать:

const spy = jest.spyOn(MyComponent.prototype, 'updateSomething');

Чтобы узнать, был ли он вызван:

expect(spy).toHaveBeenCalled();

...