如何模拟ref变量,以便我们可以基于它测试条件?

时间:2019-03-26 07:10:53

标签: unit-testing react-redux jestjs enzyme

我有一个绑定到ref变量的文件输入元素。基于上载的文件,在onChange事件中,将处理文件内容。目前,我正在编写单元测试用例以测试此功能。

App.js

export class Dashboard extends React.Component {
constructor(props) {
    this.uploadFile = React.createRef();
    //Constructing...
  }

readFileContents() {
    const files = this.uploadFile.current.files;

    for (let key in files) {
      if (files.hasOwnProperty(key)) {
        const file = files[key];
        const reader = new FileReader();
        let settings;

        // eslint-disable-next-line no-loop-func
        reader.onload = e => {
          const extension = file.name.split('.')[1];
          //OnLoad Handler
        };

        console.log(this.uploadFile.current.files)
        reader.readAsText(file); //TypeError: Failed to execute 'readAsText' on 'FileReader': parameter 1 is not of type 'Blob'.
      }
    }
  };

render() {
    return (
      <div className="dashboard wrapper m-padding">
        <div className="dashboard-header clearfix">
          <input
            type="file"
            ref={this.uploadFile}
            webkitdirectory="true"
            mozdirectory="true"
            hidden
            onChange={this.readFileContents}
            onClick={this.reset}
          />
          <Button
            outline
            className="toggle-btn float-right"
            onClick={this.openFileDialog}
          >
            Choose folder
          </Button>
        </div>
      </div>
    );
  }
}

我从这个stack overflow answer开始,能够模拟FileReader。

我最初认为,使用以下目标文件模拟更改事件,将自动反映this.uploadFile的值。

const file = new Blob([fileContents], {type : 'application/json'}); 
var event = {"target": {"files": []}};
event.target.files.push(file);

DashboardWrapper.find('input').first().simulate('change', event);

但是行为没有达到我的预期,并出现了以下错误。

  

TypeError:无法在'FileReader'上执行'readAsText':参数1不是'Blob'类型。

在此之后,我一直在尝试直接从测试文件更改ref变量中的files键,但没有结果,并且出现相同的错误。

我想首先了解我的方法是否正确。如果没有,那么正确的方法是什么?

1 个答案:

答案 0 :(得分:0)

据我了解,在单元测试中不建议测试实际的文件上传。毕竟,这些输入应该已经过彻底的测试。

话虽如此,我也有类似的要求,我也这样解决了(我正在使用VueJSJest,但是方法应该相似)

代码:

<img v-if="showLogo && currentFile" class="image-preview" :src="currentFile"/>
<input
   class="file-input"
   type="file"
   ref="fileInput"
   @change="handleFileUpload()"/>

测试:

it('should render the logo if it got uploaded', async () => {
    const wrapper = shallowMount(ApplicationLogoUpload, {
        store,
        localVue,
        propsData: {
            showLogo: true
        }
    });
    const fileInput = wrapper.find('.file-input');
    const mockedGet = jest.fn();
    mockedGet.mockReturnValue(['file1']);
    Object.defineProperty(fileInput.element, 'files', {
        get: mockedGet
    });
    fileInput.trigger('change');
    const imagePreview = wrapper.find('.image-preview');
    expect(imagePreview.attributes().src).toEqual('file1');
});

最重要的是,我使用来模拟上传的文件

const mockedGet = jest.fn();
mockedGet.mockReturnValue(['file1']);
Object.defineProperty(fileInput.element, 'files', {
    get: mockedGet
});

我通过调用upload来触发fileInput.trigger('change'); 然后,可以执行断言:src等于模拟文件。