我坚持进行img.onload
事件测试。我知道这是一个异步操作,应该对其进行模拟,但是我仍然不知道如何解决该问题。我也看到过一些类似的案例,但它们与本案例不同。
以前访问过:
要测试的代码:
function funcToTest(img, callback) {
const img = new Image()
img.src = img
img.onload = () => {
callback(true) // should return callback with true on finish
}
img.onerror = (e) => {
callback(false) // should return callback with false on error
console.log(e)
}
}
funcToTest()
测试环境:
describe('tet it', () => {
it('test', done => {
const callback = status => {
expect(status).toEqual(true) // but nothing happen
done()
}
funcToTest('some_image', callback)
})
})
我也收到一个错误:
Timeout - Async callback was not invoked within the 5000ms timeout specified by jest.setTimeout.
> 2 | it('test', done => {...
谢谢!
答案 0 :(得分:1)
这是我的解决方法:
index.ts
:
function funcToTest(imgUrl, callback) {
const img = new Image();
img.src = imgUrl;
img.onload = () => {
callback(true); // should return callback with true on finish
};
img.onerror = e => {
callback(false); // should return callback with false on error
console.log(e);
};
return img;
}
export { funcToTest };
单元测试:
/**
* @jest-environment jsdom
*/
import { funcToTest } from './';
describe('test suites', () => {
it('onload', done => {
const callback = jest.fn(status => {
expect(status).toBe(true);
done();
});
const imageUrl = 'https://github.com/mrdulin';
const img = funcToTest(imageUrl, callback);
if (img.onload) {
const event: any = {};
img.onload(event);
}
});
it('onerror', done => {
const consoleLogSpyOn = jest.spyOn(console, 'log');
const callback = jest.fn(status => {
expect(status).toBe(false);
done();
});
const imageUrl = 'https://github.com/mrdulin';
const img = funcToTest(imageUrl, callback);
if (img.onerror) {
const event: any = { message: 'some error' };
img.onerror(event);
expect(consoleLogSpyOn).toBeCalledWith(event);
}
consoleLogSpyOn.mockRestore();
});
});
单元测试结果和覆盖范围:
PASS src/stackoverflow/57092154/index.spec.ts
test suites
✓ onload (8ms)
✓ onerror (8ms)
console.log node_modules/jest-mock/build/index.js:860
{ message: 'some error' }
----------|----------|----------|----------|----------|-------------------|
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s |
----------|----------|----------|----------|----------|-------------------|
All files | 100 | 100 | 100 | 100 | |
index.ts | 100 | 100 | 100 | 100 | |
----------|----------|----------|----------|----------|-------------------|
Test Suites: 1 passed, 1 total
Tests: 2 passed, 2 total
Snapshots: 0 total
Time: 3.821s
以下是完整的演示:https://github.com/mrdulin/jest-codelab/tree/master/src/stackoverflow/57092154
答案 1 :(得分:1)
在回答此问题时,我不同意解决方案的目的。
我们不应该编写测试以通过覆盖率,而应该编写证明要点的测试,并确保代码片段表现出预期的效果。
测试它的方法是模拟Image构造函数并将其替换为将调用onload函数的东西。
describe('tet it', () => {
it('test', done => {
global.Image = class {
constructor() {
setTimeout(() => {
this.onload(); // simulate success
}, 100);
}
}
const callback = status => {
done()
}
funcToTest('some_image', callback)
})
})
该方法仅假设“浏览器”将在100毫秒内下载图像,您可以调整代码以进行故障处理,或者将其中的一部分移至beforeEach,如果需要在测试之间共享此行为。
答案 2 :(得分:1)
如果您在Image的onload
事件处理程序中有逻辑,并且想测试它是否正确应用,则可以使用{{3}以编程方式实际创建图像blob }。
考虑此功能:
const imageDimensions = (
file: File
): Promise<{ width: number; height: number }> =>
new Promise((resolve, reject) => {
const img = new Image()
img.onload = () => {
const { naturalWidth: width, naturalHeight: height } = img
resolve({ width, height })
}
img.onerror = () => {
reject('There is something wrong with this image')
}
img.src = URL.createObjectURL(file)
})`
因此,给定Canvas(blob),它将返回一个File,它解析为具有尺寸的对象。或因错误而拒绝。
我们如何测试onload
部分?您可以在测试中以编程方式创建blob,但是new Blob(['a'.repeat(10)], { type: 'image/jpeg' })
不会触发onload
,因为这实际上不是图像。
无需模拟任何东西,使用JSDOM或类似的东西。帆布救援!可以这样简单地进行测试:
describe('imageDimensions', () => {
it('should resolve with correct dimensions given an IMAGE blob', done => {
// although this canvas has no actual graphics, it is still an image and it contains image metadata, thus onload() will be fired
const canvas = document.createElement('canvas')
canvas.width = 10
canvas.height = 10
canvas.toBlob(
async blob => {
const { width, height } = await component.imageDimensions(blob)
expect(width).toBe(10)
expect(height).toBe(10)
done()
},
'image/jpeg',
0.1
)
})
it('should reject with an error if the file provided does NOT seem to be an image', async () => {
const file = new Blob(['a'.repeat(10)], { type: 'application/pdf' })
try {
await component.imageDimensions(file)
} catch (error) {
expect(error).toBe('There is something wrong with this image')
}
})
})
在此示例中,将创建Canvas,然后将其转换为blob,类似于用户选择某些图像文件时浏览器生成的blob。
P.S。这是Jest和Jasmine兼容的。