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

时间:2017-05-05 16:11:51

标签: javascript unit-testing reactjs enzyme

我对反应组件的测试看起来像这样(基于this article):

// MyComponent.test.js


import { mount } from 'enzyme';
import MyComponent from './MyComponent.jsx';

describe('<MyComponent />', () => {
  let props;
  let state;
  let mountedComponent;

  // The problematic part to be changed
  const component = () => {
    if (!mountedComponent) {
      // This enzyme mount is actually much more complex, 
      // as I'm wrapping all sorts of contexts and globals around it
      // which is why I want to take this function outside,
      // and use it as boilerplate in every test
      mountedComponent = mount(<MyComponent {...props} />);
    }
    return mountedComponent;
  };

  beforeEach(() => {
    props = {};
    state = {};
    mountedComponent = undefined;
  });

  it('Works', () => {
    state = { val: true };
    component().setState(state,
      () => expect(component().state('val')).to.equal(true),
    );
  });
});

这很有效,component()函数在同一个mountedComponent中多次调用时会正确返回相同的it,因为在调用之间保留了installedComponent的当前值,并且只重置了在每次测试之前。

现在,如果我将此测试之外的component()函数提取到另一个文件:

// getMountedComponent.js

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

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

并将component()函数替换为:

// MyComponent.test.js

// Cleaner problematic part
const component = () => getMountedComponent(MyComponent, props, mountedComponent);

然后这个测试失败了,因为component()第二次返回一个新组件,state = null。

这似乎是一个范围问题,但我无法解决这个问题?

2 个答案:

答案 0 :(得分:1)

问题是你的mountedComponent函数接受mountedComponent参数 - 实际上它在这个函数中创建了新的describle变量,所以它覆盖了getMountedComponent中定义的相同名称的变量块。因此,每次调用mountedComponent时,它都会创建新的局部变量,因此您永远不会将任何值分配给describe范围中定义的function getMountedComponent(MyComponent, props) { if (!getMountedComponent.mountedComponent) { // Appears not to properly reassign mountedComponent getMountedComponent.mountedComponent = mount(<MyComponent {...props} />); } return getMountedComponent.mountedComponent; }; 变量。要修复它,你可以在函数本身上缓存组件(函数是JS中的第一类对象)使用外部变量的插件:

delete getMountedComponent.mountedComponent;

清除功能缓存只需使用:

web: secretly-sender-web
worker: secretly-sender-worker

答案 1 :(得分:0)

Javascript by reference vs. by value

  

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

当您在getMountedComponent外部使用mountedComponent功能后,您不再在describe功能中设置undefined变量,因此将其保留为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 // ... } 的新副本。

long double d = strtold( str.c_str(), nullptr );