使用Jest和酶模拟“提交”后测试更新后的状态

时间:2020-07-15 16:49:54

标签: reactjs asynchronous jestjs enzyme setstate

所以我在React中有一个Classical组件,RecipesNew,它具有以下初始状态:

        this.state = {
            recipe: {
                title: '',
                description: '',
                prepTime: '',
                cookingTime: ''
            },
            errors: false
        }

它具有onSubmit的形式和以下方法:

        handleOnSubmit = (e) => {
            e.preventDefault()
    
            this.props.startAddRecipe(recipe)
                .then(recipe => this.props.history.push(`/recipes/${recipe._id}`))
                .catch(err => this.setState({ errors: err }))
        }

props上的startAddRecipe方法将一个Promise还原为一个Promise,该Promise会在其中的axios调用解析到我的数据库时解析,然后阻碍更新Redux状态的操作。当其中的axios调用拒绝时,promise也将拒绝。

我想测试startAddRecipe何时拒绝并设置this.state.errors。

在我的测试文件中,我有一个函数,该函数返回一个promise并立即拒绝,以作为startAddRecipe属性传递给RecipesNew:

const startAddRecipeRejectsSpy = jest.fn((recipeData = {}) => {
    return Promise.reject(['Test Error', 'Test Error 2']) 
})

这是我对Promise拒绝时的测试。我以为state.errors将填充以下数组:['Test Error','Test Error 2']

test('startAddRecipe rejects correctly', () => {

    const wrapper = shallow(<RecipesNew startAddRecipe={startAddRecipeRejectsSpy} />);
    const mockRecipe = {
        title: 'Test Title',
        description: 'Test Description',
        prepTime: 10,
        cookingTime: 10
    }
    wrapper.setState({ recipe: mockRecipe })
    wrapper.find('form').simulate('submit',{ preventDefault: () => { } })
    expect(startAddRecipeRejectsSpy).toHaveBeenLastCalledWith(mockRecipe)
    expect(startAddRecipeRejectsSpy(mockRecipe)).rejects.toEqual(['Test Error', 'Test Error 2'])
    expect(wrapper.update().state().errors).toBe(['Test Error', 'Test Error 2']);
    expect(wrapper.update()).toMatchSnapshot();
})

一切都与最后2个分开。

倒数第二个说:

    Expected: ["Test Error", "Test Error 2"]
    Received: false

所以基本上状态似乎没有改变?

最后,最后一个快照不是我所期望的,因为this.state.errors不是虚假时,我将映射到错误数组上并生成一个列表-该列表不会出现在快照中。

有什么想法吗?我已经阅读了很多有关此问题的主题,但似乎没有任何问题与我的问题相符。

任何帮助表示赞赏。

谢谢!

1 个答案:

答案 0 :(得分:0)

startAddRecipe是异步的,因此它可能在测试完成之前未完成。您需要等待startAddRecipe完成才能检查状态。您可以通过执行类似的操作来确保在检查状态之前刷新所有的Promise。

const tick = async () => {
  return new Promise((resolve) => {
    setTimeout(resolve, 0);
  });
};

.
.

test('startAddRecipe rejects correctly', async () => {

    const wrapper = shallow(<RecipesNew startAddRecipe={startAddRecipeRejectsSpy} />);
    const mockRecipe = {
        title: 'Test Title',
        description: 'Test Description',
        prepTime: 10,
        cookingTime: 10
    }
    wrapper.setState({ recipe: mockRecipe })
    wrapper.find('form').simulate('submit',{ preventDefault: () => { } })
    await tick();
    expect(startAddRecipeRejectsSpy).toHaveBeenLastCalledWith(mockRecipe)
    expect(startAddRecipeRejectsSpy(mockRecipe)).rejects.toEqual(['Test Error', 'Test Error 2'])
    expect(wrapper.update().state().errors).toBe(['Test Error', 'Test Error 2']);
    expect(wrapper.update()).toMatchSnapshot();
})

给个镜头,让我知道它是否对您有用。