问题
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