【发布时间】:2018-11-13 09:07:14
【问题描述】:
我正在尝试模拟默认 DOM Image 对象以对 Angular 服务进行单元测试。
服务很简单,它检查“webP”格式支持:
import {Injectable} from '@angular/core';
import {Promise} from 'es6-promise';
import {environment} from '../../../../environments/environment';
@Injectable({
providedIn: 'root'
})
export class AppLoadService {
constructor() {
}
initializeApp(): Promise<any> {
return new Promise((resolve) => {
console.log(`initializeApp:: inside promise`);
if (typeof Image === 'undefined') {
console.log(`initializeApp:: Image undefined`);
resolve();
return;
}
const webP = new Image();
webP.onload = () => {
console.log(`initializeApp:: WebP support: true`);
environment.webP = true;
resolve();
};
webP.onerror = () => {
console.log(`initializeApp:: WebP support: false`);
resolve();
};
webP.src = 'data:image/webp;base64,UklGRjoAAABXRUJQVlA4IC4AAACyAgCdASoCAAIALmk0mk0iIiIiIgBoSygABc6WWgAA/veff/0PP8bA//LwYAAA';
});
}
}
我找到了一种检查 webP 支持的方法(默认在运行 Karma 的 chromium 中),以及一种检查 Image undefined 的回退方法。
但我找不到检查onerror 后备的方法...
这是我的规范文件:
import {TestBed} from '@angular/core/testing';
import {AppLoadService} from './app-load.service';
import {environment} from '../../../../environments/environment';
describe('AppLoadService', () => {
let service: AppLoadService;
const originalImage = Image;
beforeEach(() => TestBed.configureTestingModule({}));
beforeEach(() => {
service = TestBed.get(AppLoadService);
});
it('should be created', () => {
expect(service).toBeTruthy();
});
it('should resolve with webP', (done) => {
const test = () => {
Image = originalImage;
service.initializeApp().then(() => {
expect(environment.webP).toBe(true);
done();
});
};
test();
});
it('should resolve without webP (A)', (done) => {
const test = () => {
Image = undefined;
service.initializeApp().then(() => {
expect(environment.webP).toBe(false);
done();
});
};
test();
});
it('should resolve without webP (B)', (done) => {
// How to force Image to throw "onerror" ?
const test = () => {
Image = originalImage;
service.initializeApp().then(() => {
expect(environment.webP).toBe(false);
done();
});
};
test();
});
});
问题在should resolve without webP (B)测试,在文件末尾..
此外,有没有更好的方法来检查未定义的 Image 对象或onload 回调?
谢谢!
编辑
无法让它按原样工作,所以我更改服务构造函数以提供“图像”依赖项。
constructor(@Inject('Image') image: typeof Image) {
this.image = image;
}
必须像这样加载模块:
providers: [
AppLoadService,
// [...]
{provide: 'Image', useValue: Image},
]
每个resolve() 现在都包含environment.webP 结果。否则,单独测试真的很痛苦,environment 在测试前被随机重写。
使用一个简单的 Mock,它的工作原理如下:
import {TestBed} from '@angular/core/testing';
import {AppLoadService} from './app-load.service';
class MockImageFail {
public onerror: Function;
private _src: string;
set src(src) {
this._src = src;
if (this.onerror) {
this.onerror();
}
}
}
describe('AppLoadService', () => {
beforeEach(() => {
TestBed.configureTestingModule({
providers: [{provide: 'Image', useValue: Image}]
});
});
it('should be created', () => {
const service = TestBed.get(AppLoadService);
expect(service).toBeTruthy();
});
it('should resolve with webP', (done) => {
const service = TestBed.get(AppLoadService);
service.initializeApp().then((supportWebP) => {
expect(supportWebP).toBe(true);
done();
});
});
it('should not resolve without webP (A)', (done) => {
TestBed.overrideProvider('Image', {useValue: undefined});
const service = TestBed.get(AppLoadService);
service.initializeApp().then((supportWebP) => {
expect(supportWebP).toBe(false);
done();
});
});
it('should not resolve without webP (B)', (done) => {
TestBed.overrideProvider('Image', {useValue: MockImageFail});
const service = TestBed.get(AppLoadService);
service.initializeApp().then((supportWebP) => {
expect(supportWebP).toBe(false);
done();
});
});
});
我对此并不满意,我相信还有另一种更好的方法:/
【问题讨论】:
标签: angular image dom karma-jasmine angular7