Reactjs 在React&;重演

Reactjs 在React&;重演,reactjs,mocha.js,redux,enzyme,Reactjs,Mocha.js,Redux,Enzyme,我有一个组件SampleComponent,它安装了另一个“连接的组件”(即容器)。当我尝试通过mounting测试SampleComponent时(因为我需要componentDidMount),我得到了错误: 不变冲突:在上下文或上下文中找不到“存储” “连接(集装箱组件)”的道具。或者包装根组件 在中,或显式地将“store”作为道具传递给 “连接(集装箱组件)” 测试这一点的最佳方法是什么?我基本上是将我的redux存储(和Provider)放入实用程序组件中,如下所示: export

我有一个组件
SampleComponent
,它安装了另一个“连接的组件”(即
容器
)。当我尝试通过
mount
ing测试
SampleComponent
时(因为我需要
componentDidMount
),我得到了错误:

不变冲突:在上下文或上下文中找不到“存储” “连接(集装箱组件)”的道具。或者包装根组件 在中,或显式地将“store”作为道具传递给 “连接(集装箱组件)”


测试这一点的最佳方法是什么?

我基本上是将我的
redux
存储(和
Provider
)放入实用程序组件中,如下所示:

export const CustomProvider = ({ children }) => {
  return (
    <Provider store={store}>
      {children}
    </Provider>
  );
};

酶的装载量采用可选参数。你所需要的两件事是

options.context:(对象[可选]:要传递到组件中的上下文

options.childContextTypes:(对象[可选]):包装器所有子级的合并contextTypes
您可以使用如下选项对象装载
SampleComponent

const store = { 
  subscribe: () => {},
  dispatch: () => {},
  getState: () => ({ ... whatever state you need to pass in ... })
}
const options = {
  context: { store }, 
  childContextTypes: { store: React.PropTypes.object.isRequired } 
}

const _wrapper = mount(<SampleComponent {...defaultProps} />, options)
conststore={
订阅:()=>{},
调度:()=>{},
getState:()=>({…需要传入的任何状态…})
}
常量选项={
上下文:{store},
childContextTypes:{store:React.PropTypes.object.isRequired}
}
常量包装器=装载(,选项)

现在,您的SampleComponent将把您提供的上下文传递给连接的组件

,您可以使用名称导出来解决此问题:

你应该:

class SampleComponent extends React.Component{
...
   render(){
       <div></div>
   }
}

export default connect(mapStateToProps, mapDispatchToProps)(SampleComponent)
并在没有redux存储的情况下导入此组件:

import { SampleComponent } from 'your-path/SampleComponent';
使用此解决方案,您无需将存储导入测试文件。

选项1) 您可以在测试中使用React-Redux的提供者组件包装容器组件。因此,使用这种方法,您实际上引用了存储,将其传递给提供者,并在内部组成您的测试组件。这种方法的优点是您实际上可以为测试创建一个自定义存储。如果您想测试组件中与Redux相关的部分,这种方法非常有用

备选方案2) 也许你不在乎测试Redux相关的部分。如果您只是对测试组件的渲染和与本地状态相关的行为感兴趣,那么只需为组件的未连接普通版本添加命名导出即可。为了澄清一下,当你把“export”关键字添加到你的类中时,你基本上是说现在这个类可以用两种方式导入,要么用大括号{},要么不用大括号。例如:

export class MyComponent extends React.Component{ render(){ ... }}

...

export default connect(mapStateToProps, mapDispatchToProps)(MyComponent)
稍后在您的测试文件上:

import MyComponent from 'your-path/MyComponent'; // it needs a store because you use "default export" with connect
import {MyComponent} from 'your-path/MyComponent'; // don't need store because you use "export" on top of your class.
@anyOldClassDecorator
export class AnyOldClass {
  @anyOldMethodDecorator
  method() {
    console.log('hello');   
  }
}
@anyOldClassDecorator
export class AnyOldClass {
  @anyOldMethodDecorator
  method() {
    console.log('hello');   
  }
}

export class __undecorated__AnyOldClass {
  method() {
    console.log('hello');   
  }
}

我希望能帮助任何人。

为了使decorator语法的使用更易于测试,我做了以下几点:

输入:

import MyComponent from 'your-path/MyComponent'; // it needs a store because you use "default export" with connect
import {MyComponent} from 'your-path/MyComponent'; // don't need store because you use "export" on top of your class.
@anyOldClassDecorator
export class AnyOldClass {
  @anyOldMethodDecorator
  method() {
    console.log('hello');   
  }
}
@anyOldClassDecorator
export class AnyOldClass {
  @anyOldMethodDecorator
  method() {
    console.log('hello');   
  }
}

export class __undecorated__AnyOldClass {
  method() {
    console.log('hello');   
  }
}
输出:

import MyComponent from 'your-path/MyComponent'; // it needs a store because you use "default export" with connect
import {MyComponent} from 'your-path/MyComponent'; // don't need store because you use "export" on top of your class.
@anyOldClassDecorator
export class AnyOldClass {
  @anyOldMethodDecorator
  method() {
    console.log('hello');   
  }
}
@anyOldClassDecorator
export class AnyOldClass {
  @anyOldMethodDecorator
  method() {
    console.log('hello');   
  }
}

export class __undecorated__AnyOldClass {
  method() {
    console.log('hello');   
  }
}

希望这能提供一个可靠的选项3

还可以选择使用

用于测试Redux异步操作创建者和中间件的模拟存储。模拟存储区将创建一个调度操作数组,作为测试的操作日志

模拟存储区在存储区对象上提供了Redux所需的必要方法。 您可以指定可选的中间件和特定于应用程序的初始状态

import configureStore from 'redux-mock-store'

const middlewares = []
const mockStore = configureStore(middlewares)

const initialState = {}
const store = mockStore(initialState)

const wrapper = mount(<SampleComponent store={store}/>)
从“redux模拟存储”导入配置存储
const middleware=[]
const mockStore=configureStore(中间件)
常量initialState={}
常量存储=模拟存储(初始状态)
const wrapper=mount()

我看到您正在使用mount,如果我试图用
shallo
替换
mount
,我会得到一个错误。您也遇到过这种情况吗?虽然这个答案在某些情况下有效,但当您需要测试组件的生命周期时,它就不起作用了。例如,调用
wrapper.setProps()
不会在
SampleComponent
上触发
componentWillReceiveProps()
。这太完美了!虽然公认的答案在大多数情况下都有效,但缺点是您无法充分使用mountapi。例如,使用在
提供程序中包装组件的公认答案将不允许使用
wrapper.state()
api。此解决方案将为您的包装提供完整的方法。这是一个比公认的答案更好的答案,原因如下(即,您安装的包装实际上不是您尝试测试的组件),并且还因为您可以使用模拟存储而不是实际存储,将所有redux都排除在等式之外。此可选参数不在文档中,您是如何找到它的?在代码中?如果
SampleComponent
使用一个名为
SubComponent
的连接组件,并且我们希望使用
mount
检查它是否正确呈现(集成测试,而不是单元),该怎么办?您可以将存储作为第二个参数传递给
SampleComponent
,但是
SubComponent
将没有存储。由于Ezyme v3,浅层调用ComponentDidMount FYI