Я пытаюсь создать функцию для жасмина, которая шпионит за полным объектом, включая методы, сеттеры и геттеры.Фабрика выглядит следующим образом:
// @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();
В самом компоненте я вижукартинки $ не определены.Но, отлаживая тест, я вижу, что он определен, когда я предоставляю экземпляр.Кроме того, сделав что-то, как перед предоставлением:
const val = (<any>stateServiceMock).pictures$;
(<any>stateServiceMock).pictures2 = val;
Фактически передает свойство с именем pictures2 в Компонент, но не рисунки $: 
Isчто-нибудь Angular делает с объектом, предоставленным useValue, что может объяснить, почему я «теряю» свойства, хотя они установлены точно?