Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/405.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 单元测试中的可变范围问题_Javascript_Unit Testing_Reactjs_Enzyme - Fatal编程技术网

Javascript 单元测试中的可变范围问题

Javascript 单元测试中的可变范围问题,javascript,unit-testing,reactjs,enzyme,Javascript,Unit Testing,Reactjs,Enzyme,我对react组件的测试如下所示(基于): 并将组件()函数替换为: // MyComponent.test.js // Cleaner problematic part const component = () => getMountedComponent(MyComponent, props, mountedComponent); 然后该测试失败,因为component()第二次返回一个新组件,状态为null 这似乎是一个范围问题,但我无法理解这一点。 Javascript总是按值

我对react组件的测试如下所示(基于):

并将
组件()
函数替换为:

// MyComponent.test.js

// Cleaner problematic part
const component = () => getMountedComponent(MyComponent, props, mountedComponent);
然后该测试失败,因为component()第二次返回一个新组件,状态为null

这似乎是一个范围问题,但我无法理解这一点。

Javascript总是按值传递,但当变量引用 对象(包括数组),“值”是对该对象的引用

当您将
getMountedComponent
函数置于外部时,您不再在
description
函数中设置
mountedComponent
变量,因此它将
保留为未定义的
,因此它将每次创建
mountedComponent
的新副本

const getMountedComponent = (MyComponent, props, mountedComponent) => {

  if (!mountedComponent) {
    // You are not changing the "mountedComponent" defined in your "describe" here
    // because "mountedComponent" is pass by value
    mountedComponent = mount(<MyComponent {...props} />);
  }
  return mountedComponent;
};

describe('<MyComponent />', () => {
  let props;
  let state;
  let mountedComponent; // This stays undefined
  // ...
}
const getMountedComponent=(MyComponent,props,mountedComponent)=>{
如果(!mountedComponent){
//您没有更改此处“描述”中定义的“mountedComponent”
//因为“mountedComponent”是按值传递的
mountedComponent=mount();
}
返回安装组件;
};
描述(“”,()=>{
让道具;
让国家;
let mountedComponent;//这将保持未定义状态
// ...
}

问题在于
getMountedComponent
函数接受
mountedComponent
参数-实际上它在该函数中创建了新的
mountedComponent
变量,因此它会覆盖
describle
块中定义的同名变量。因此每次调用
getMountedComponent
>它会创建新的局部变量,因此您不会将任何值赋给
descripe
范围中定义的
mountedComponent
变量。要修复此问题,您可以在函数本身(函数在JS中是一级对象)上缓存组件,而不用使用外部变量:

function getMountedComponent(MyComponent, props) {

  if (!getMountedComponent.mountedComponent) {
    // Appears not to properly reassign mountedComponent
    getMountedComponent.mountedComponent = mount(<MyComponent {...props} />);
  }
  return getMountedComponent.mountedComponent;
};

我将函数从descripe函数中拉出的原因是,它实际上比我解释的要复杂一些。这意味着我希望
getMountedComponent
存在于另一个文件中。很漂亮!它工作了:)我立即用它编写了一个函数:
getMountedComponent.reset=()=>{删除getMountedComponent.mountedComponent;}
Great:)是的,添加一个清除缓存的方法是一个非常好的主意:)我之所以使用
mountedComponent
,是为了能够在每次之前在
中重置它,因为我实际上在这里运行了很多测试。同意,对于单个测试来说,它是没有用的。因为mountedComponent最终引用了React组件,这是一个object,如果您再次调用该函数,我希望它通过引用传递,这是错误的吗?@FlorianBienefelt我明白了,我将删除答案的这一部分。不过,最初,您的变量不是对象,因此它将保持未定义状态。即使使用对象,您也只能修改其属性,因此您不能将其作为某个新组件进行分配。@FlorianBienefelt忽略“最初,您的变量不是对象,因此它将保持未定义状态。”。即使使用对象,也会将引用的值传递给函数。因此,如果执行
mountedComponent=foo
,则不会更改该引用中的内容,而只是替换了引用的值。这有点难以解释…我希望我讲得有点道理。
const getMountedComponent = (MyComponent, props, mountedComponent) => {

  if (!mountedComponent) {
    // You are not changing the "mountedComponent" defined in your "describe" here
    // because "mountedComponent" is pass by value
    mountedComponent = mount(<MyComponent {...props} />);
  }
  return mountedComponent;
};

describe('<MyComponent />', () => {
  let props;
  let state;
  let mountedComponent; // This stays undefined
  // ...
}
function getMountedComponent(MyComponent, props) {

  if (!getMountedComponent.mountedComponent) {
    // Appears not to properly reassign mountedComponent
    getMountedComponent.mountedComponent = mount(<MyComponent {...props} />);
  }
  return getMountedComponent.mountedComponent;
};
delete getMountedComponent.mountedComponent;