how to mock failure of FileReader

烈酒焚心 提交于 2021-01-27 22:08:08

问题


I have a function which creates a FileReader. In that function I also set the load and error event handlers

handleFileSelect(files:ArrayLike<File>){
...
      let reader = new FileReader()
      reader.onload = this.handleReaderLoaded;
      reader.onerror = this.handleReaderError;


      reader.readAsDataURL(file);
    }
  }

I want to unit-test that handleFileSelect correctly sets the error handler and that the error handler (handleReaderError) gets called if FileReader fails. But I can't figure out how to make the FileReader fail.

The spec I have written so far is

fit('should call error handler when file doesn\'t get loaded successfully', (done) => {
    let newPracticeQuestionComponent = component;

    let file1 = new File(["foo1"], "foo1.txt");
    /*
    File reader will load the file asynchronously.
    The `done` method of `Jasmine` makes `Jasmine` wait
    When handleReaderError is called, call a fake function and within it call done
     */
    spyOn(newPracticeQuestionComponent,'handleReaderError').and.callFake(function(event:FileReaderProgressEvent){
      console.log("called fake implementation of handleReaderError ",event);
      expect(event.type).toEqual("abort");
      done();
    });

    newPracticeQuestionComponent.handleFileSelect([file1]);
//I SHOULD SIMULATE FILEREADER ERROR HERE BUT HOW??

  });

回答1:


If the reader's behaviour is calling onerror when readAsDataURL fails, this should do:

spyOn(newPracticeQuestionComponent.reader, 'readAsDataURL').and.callFake(() => {
    newPracticeQuestionComponent.reader.onerror();
});

Since this will be running as a synchronous call, you can simplify the assertion at the end of the test (following a triple A) like this:

// Arrange
const newPracticeQuestionComponent = component;
spyOn(newPracticeQuestionComponent, 'handleReaderError');
spyOn(newPracticeQuestionComponent.reader, 'readAsDataURL').and.callFake(() => {
    newPracticeQuestionComponent.reader.onerror();
});
let file1 = new File(["foo1"], "foo1.txt");

// Act
newPracticeQuestionComponent.handleFileSelect([file1]);

// Assert
expect(newPracticeQuestionComponent.handleReaderError).toHaveBeenCalledWith({ type: 'abort' });

But I don't recommend expecting the parameter passes to the function, event.type, because it is the specification of another unit that we are not currently testing. (we are testing newPracticeQuestionComponent not the behaviour of reader calling an error with an event)


Mocking the behaviour of reader might not be the best way. It depends on what you want to test against the unit.

In case we want to go extremely independent, newPracticeQuestionComponent should know nothing about reader's behaviour even the callback error, the only thing this unit should know is to set the onerror callback, you can just assert that you set the onerror of reader correctly.

// Arrange
const newPracticeQuestionComponent = component;
spyOn(newPracticeQuestionComponent.reader, 'readAsDataURL');
let file1 = new File(["foo1"], "foo1.txt");

// Act
newPracticeQuestionComponent.handleFileSelect([file1]);

// Assert
expect(newPracticeQuestionComponent.reader.onerror).toBe(newPracticeQuestionComponent.handleReaderError);

I am no master about testing, but it seems to be pros and cons writing tests like the above and below examples upon many factors.

Hope this helps :)



来源:https://stackoverflow.com/questions/54316822/how-to-mock-failure-of-filereader

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!