我正在尝试为茉莉花创建一个函数,该函数监视一个完整的对象,包括方法,设置器和获取器。工厂看起来像这样:
// @dynamic
export class SpyFactoryService {
public static createSpy<T>(spiedClass: Type<T>): SpyOf<T> {
const functionNames = this.getFunctionNames(spiedClass).map(f => f.propertyName);
// Add the functions
const result = jasmine.createSpyObj('spy', [...functionNames]);
// Add "empty" setters per setter-property of the spied Class
this.getSetters(spiedClass)
.map(prop => {
Object.defineProperty(result, prop.propertyName, {
set: function () {
}
});
});
// Add getters, which return undefined, for each getter-property of the spied Class
this.getGetters(spiedClass)
.map(prop => {
Object.defineProperty(result, prop.propertyName, {
get: function () {
return undefined;
}
});
});
return result;
}
private static getFunctionNames<T>(spiedClass: Type<T>): ObjectProperty[] {
return this.getObjects(spiedClass).filter(prop => prop.propertyDescriptor.value instanceof Function);
}
private static getGetters<T>(spiedClass: Type<T>): ObjectProperty[] {
return this.getObjects(spiedClass).filter(prop => prop.propertyDescriptor.get);
}
private static getObjects<T>(spiedClass: Type<T>): ObjectProperty[] {
const prototype = spiedClass.prototype;
const result = Object.getOwnPropertyNames(prototype)
.filter(name => !!Object.getOwnPropertyDescriptor(prototype, name))
.map(name => new ObjectProperty(name, Object.getOwnPropertyDescriptor(prototype, name)!));
return result;
}
private static getSetters<T>(spiedClass: Type<T>): ObjectProperty[] {
return this.getObjects(spiedClass).filter(prop => prop.propertyDescriptor.set);
}
}
代码不是很漂亮,但是它为每个函数以及“空”属性返回了一组间谍,让我以后可以监视它们,例如:
const stateServiceMock = SpyFactoryService.createSpy(ConstructionDefectPicturesStateService);
spyOnProperty(stateServiceMock, 'pictures$', 'get').and.returnValue(new BehaviorSubject<ConstructionDefectPictureDto[]>([]));
不幸的是,有一件奇怪的事:假设我使用名为$ pictures的属性设置了一个测试,如下所示:
beforeEach(async(() => {
const stateServiceMock = SpyFactoryService.createSpy(ConstructionDefectPicturesStateService);
spyOnProperty(stateServiceMock, 'pictures$', 'get').and.returnValue(new BehaviorSubject<ConstructionDefectPictureDto[]>([]));
TestBed.configureTestingModule({
declarations: [ConstructionDefectPicturesComponent],
schemas: [NO_ERRORS_SCHEMA],
providers: [
{
provide: ConstructionDefectPicturesStateService,
useValue: stateServiceMock
}
]
})
.compileComponents();
在组件本身中,我看到picture $是未定义的。但是调试调试后,在提供实例时,我看到它已定义。另外,在提供之前做类似的事情:
const val = (<any>stateServiceMock).pictures$;
(<any>stateServiceMock).pictures2 = val;
实际上是否将一个名为pictures2的属性传递给Component,而不是pictures $:
Angular对useValue提供的对象有什么用,可以解释为什么我“失去了”属性,尽管可以确定设置了这些属性?