Angular Dependency Injection удаляет динамически добавленные свойства - PullRequest
0 голосов
/ 28 февраля 2019

Я пытаюсь создать функцию для жасмина, которая шпионит за полным объектом, включая методы, сеттеры и геттеры.Фабрика выглядит следующим образом:

// @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 в Компонент, но не рисунки $: enter image description here

Isчто-нибудь Angular делает с объектом, предоставленным useValue, что может объяснить, почему я «теряю» свойства, хотя они установлены точно?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...