Javascript 如何在jest和Ezyme中设置useState钩子的初始状态?

Javascript 如何在jest和Ezyme中设置useState钩子的初始状态?,javascript,reactjs,enzyme,react-hooks,react-hooks-testing-library,Javascript,Reactjs,Enzyme,React Hooks,React Hooks Testing Library,目前我正在使用带有react钩子的功能组件。但是我无法完全测试useStatehook。考虑一个场景,比如使用效果 HOOK,我正在API代码中调用API,并在 UsStave中设置值。对于jest/Ezyme,我已经模拟了要测试的数据,但是我无法在jest中为useState设置初始状态值 const[state,setState]=useState([]) 我想将初始状态设置为对象数组。我找不到任何类似于类组件的setState函数。您可以模拟反应。使用state在测试中返回不同的初始状态:

目前我正在使用带有react钩子的功能组件。但是我无法完全测试
useState
hook。考虑一个场景,比如<代码>使用效果 HOOK,我正在API代码中调用API,并在<代码> UsStave<代码>中设置值。对于jest/Ezyme,我已经模拟了要测试的数据,但是我无法在jest中为
useState
设置初始状态值

const[state,setState]=useState([])


我想将初始状态设置为对象数组。我找不到任何类似于类组件的setState函数。

您可以模拟
反应。使用state
在测试中返回不同的初始状态:

// Cache original functionality
const realUseState = React.useState

// Stub the initial state
const stubInitialState = ['stub data']

// Mock useState before rendering your component
jest
  .spyOn(React, 'useState')
  .mockImplementationOnce(() => realUseState(stubInitialState))

Reference:

如果我没记错的话,你应该尽量避免模仿内置的钩子,比如
useState
useffect
。如果使用Ezyme的
invoke()
很难触发状态更改,那么这可能表明您的组件将从分解中受益。

  • 下面的函数将返回状态
  • 添加以下内容以使用react
const reactMock=require('react')

在代码中,必须使用
React.useState()
来完成此工作,否则它将无法工作

const[ArrayValue,SetArrayValue]=React.useState()

const[isFetching,setFetching]=React.useState()

  • 然后在测试中添加以下模拟状态值
reactMock.useState=setHookState({
数组值:[],
isFetching:false,
});

灵感:

//组件
常量MyComponent=({someColl,someId})=>{
const[myState,setMyState]=useState(null);
useEffect(()=>{每次设置组时循环
if(groupId){
const runEffect=async()=>{
const data=someColl.find(s=>s.id=someId);
setMyState(数据);
};
runEffect();
}
},[someId,someColl]);
返回({myState.name});
};
//试验
//嘲弄
const mockSetState=jest.fn();
mock('react',()=>({
…开玩笑,要求反应('react'),
useState:initial=>[初始,mockSetState]
}));
const coll=[{id:1,名称:'Test'},{id:2,名称:'Test2'}];
它('使用groupId正确呈现',()=>{
常数包装=浅(
);
设置超时(()=>{
expect(wrapper.toMatchSnapshot();
expect(mockSetState).tohavencalledwith({id:1,name:'Test'});
}, 100);
});

首先,您不能在组件中使用解构。例如,您不能使用:

import React, { useState } from 'react';
const [myState, setMyState] = useState();
相反,您必须使用:

import React from 'react'
const [myState, setMyState] = React.useState();
然后在
test.js
文件中:

test('useState mock', () => {
   const myInitialState = 'My Initial State'

   React.useState = jest.fn().mockReturnValue([myInitialState, {}])
   
   const wrapper = shallow(<MyComponent />)

   // initial state is set and you can now test your component 
}
test('useState mock',()=>{
const myInitialState='我的初始状态'
React.useState=jest.fn().mockReturnValue([myInitialState,{}])
常量包装器=浅()
//初始状态已设置,现在可以测试组件
}
如果在组件中多次使用useState钩子:

// in MyComponent.js

import React from 'react'

const [myFirstState, setMyFirstState] = React.useState();
const [mySecondState, setMySecondState] = React.useState();

// in MyComponent.test.js

test('useState mock', () => {
   const initialStateForFirstUseStateCall = 'My First Initial State'
   const initialStateForSecondUseStateCall = 'My Second Initial State'

   React.useState = jest.fn()
     .mockReturnValueOnce([initialStateForFirstUseStateCall, {}])
     .mockReturnValueOnce([initialStateForSecondUseStateCall, {}])
   
   const wrapper = shallow(<MyComponent />)

   // initial states are set and you can now test your component 
}
// actually testing of many `useEffect` calls sequentially as shown
// above makes your test fragile. I would recommend to use 
// `useReducer` instead.
//在MyComponent.js中
从“React”导入React
const[myFirstState,setMyFirstState]=React.useState();
const[mySecondState,setMySecondState]=React.useState();
//在MyComponent.test.js中
测试('useState mock',()=>{
const initialStateForFirstUseStateCall='我的第一个初始状态'
const initialstateforSecondustestateCall='我的第二个初始状态'
React.useState=jest.fn()
.mockReturnValueOnce([initialStateForFirstUseStateCall,{}])
.mockReturnValueOnce([InitialStateforSecondUserStateCall,{}])
常量包装器=浅()
//初始状态已设置,您现在可以测试组件
}
//如图所示,实际按顺序测试许多“useEffect”调用
//以上内容使您的测试变得脆弱。我建议您使用
//改为“useReducer”。

show code Please是否可以共享完整的组件代码和错误?不要。测试组件对用户的外观,而不是内部功能。如果组件中有多个useState语句,该怎么办?使用一系列mockImplementationOnce()模拟多个useState.看看如果你不知道调用useState的顺序会怎样?我有一个复杂的应用程序,有很多useState。我可能现在不应该测试实现。如何获取返回状态值,可能吗?比如下面的
const[formSend,setArrayValues]=React.useState();
@BenButterworth你找到了答案吗?我的情况和你一样-我不能模拟useState,因为我在我的组件中使用它;我不能使用MockImplementation一次,因为我不确定useState将被调用多少次。你如何将reactMock传递给安装的组件?你不必这样做,因为你正在为我模拟react hooksWorks中的useState函数,谢谢。我还使用了来自“react”的
import react,{useState};
,因此您可以通过这种方法自由使用扩展版的
useState
。在您的代码中,必须使用react.useState()来完成此工作,否则它将无法工作。我们如何使用useState()直接没有反应?我只用useState()试过,但它对meExactly不起作用。与其模拟状态,不如通过UI与组件交互和/或模拟外部API响应来触发状态更改。钩子是实现细节。您能详细说明为什么我们不能使用解构吗?因为据我所知,这是React组件的法律代码。
test('useState mock', () => {
   const myInitialState = 'My Initial State'

   React.useState = jest.fn().mockReturnValue([myInitialState, {}])
   
   const wrapper = shallow(<MyComponent />)

   // initial state is set and you can now test your component 
}
// in MyComponent.js

import React from 'react'

const [myFirstState, setMyFirstState] = React.useState();
const [mySecondState, setMySecondState] = React.useState();

// in MyComponent.test.js

test('useState mock', () => {
   const initialStateForFirstUseStateCall = 'My First Initial State'
   const initialStateForSecondUseStateCall = 'My Second Initial State'

   React.useState = jest.fn()
     .mockReturnValueOnce([initialStateForFirstUseStateCall, {}])
     .mockReturnValueOnce([initialStateForSecondUseStateCall, {}])
   
   const wrapper = shallow(<MyComponent />)

   // initial states are set and you can now test your component 
}
// actually testing of many `useEffect` calls sequentially as shown
// above makes your test fragile. I would recommend to use 
// `useReducer` instead.