.detectChanges () не работает в угловом тесте - PullRequest
0 голосов
/ 02 мая 2018

Мне было поручено написать тесты для приложения для чата, разработанного на Angular. Ниже приведен фрагмент кода шаблона Angular, для которого я сейчас пишу тесты:

<div class="title-menu-container" fxLayoutAlign="center center">
  <button id="save-title-button" mat-icon-button *ngIf="titleInputEdit; else settings">
    <mat-icon class="secondary-text" (click)="saveTitle(titleInput.value)">check</mat-icon>
  </button>
  <ng-template #settings>
    <button mat-icon-button [matMenuTriggerFor]="menu" [disabled]="!(isGroupConversation$ | async)">
      <mat-icon class="secondary-text">settings</mat-icon>
    </button>
  </ng-template>
</div>

По сути, если булева переменная компонента 'titleInputEdit' имеет значение true, отображается кнопка сохранения заголовка, в противном случае отображается кнопка настроек. Вот тестовый пример, который вызывает проблемы:

it('save title button should be present', () => {
  component.titleInputEdit = true;
  fixture.detectChanges();
  expect(fixture.nativeElement.querySelector('#save-title-button')).not.toBe(null);
}); 

Я просто «высмеиваю» переменную компонента, вызываю .detectChanges () и проверяю наличие кнопки. Тем не менее, тест не пройден с «Ожидаемый ноль не будет нулевым».

С помощью различных вызовов console.log я подтвердил, что для component.titleInputEdit правильно установлено значение true, но fixture.nativeElement НЕ содержит правильную кнопку.

Некоторые вещи, которые я заметил:

  • Если я переместлю строку 'component.titleInputEdit = true' в мой beforeEach и удалю ее, и вызов функции visibleChanges () из моего теста будет пройден.

    beforeEach(() => {
      fixture = TestBed.createComponent(TestComponent);
      component = fixture.componentInstance;
      component.titleInputEdit = true
      fixture.detectChanges();
      debugElement = fixture.debugElement;
    });     
    
    it('save title button should be present', () => {
        expect(fixture.nativeElement.querySelector('#save-title-button')).not.toBe(null);
    });
    
  • Если я удаляю вызов .detectChanges () из beforeEach () и оставляю его в тестовом примере, тест проходит.

Я относительно новичок в Angular, но я встречал людей с похожей проблемой. После того, как я попробовал кое-что из того, что было рекомендовано в этих постах, я все еще остаюсь, почесывая голову Еще более странным является то, что я написал тесты для других компонентов Angular, которые делают практически то же самое без проблем.

Пример, приведенный в документах Angular, также показывает нечто очень похожее:

it('should display a different test title', () => {
  component.title = 'Test Title';
  fixture.detectChanges();
  expect(h1.textContent).toContain('Test Title');
});    

Ответы [ 3 ]

0 голосов
/ 27 июля 2018

Ответ, предоставленный здесь https://stackoverflow.com/a/50142134/3765819, решает проблему. Однако есть и другой способ, который, я думаю, может предотвратить дальнейшие проблемы с пользовательским интерфейсом. У меня была похожая проблема, описанная в вопросе, и это означало, что при тестировании определенной строки в HTML я не смог ее найти. Несмотря на то, что при запуске кода он работал хорошо, пользовательский интерфейс не обновлялся соответствующим образом при его тестировании.

Что мне нужно было сделать:

Для добавления ChangeDetectorRef в файл .ts:

constructor(private changeDetector: ChangeDetectorRef) {}

и при необходимости позвоните:

this.changeDetector.markForCheck();
0 голосов
/ 11 июня 2019

Я знаю, что этот вопрос старый, но у меня недавно была та же самая проблема, когда спиннер постоянно вращался на странице Кармы, потому что обнаружение изменений происходило только один раз. Для меня исправление: вызвать ли fixture.detectChanges (true) или fixture.autoDetectChanges (true).

beforeEach(() => { 
  fixture = TestBed.createComponent(TestComponent);
  component = fixture.componentInstance;
  component.titleInputEdit = true
  // 'detectChanges' will only test for onPush events: 
  // fixture.detectChanges();

  // 'autoDetectChanges' will continually check for changes until the test is complete.  
  // This is slower, but necessary for certain UI changes
  fixture.autoDetectChanges(true);

  debugElement = fixture.debugElement;
}); 
0 голосов
/ 02 мая 2018

Оказывается, это связано с использованием ChangeDetectionStrategy.OnPush в компоненте. Использование OnPush позволяет вам вызывать .detectChanges () только один раз, поэтому последующие вызовы ничего не сделают. Я недостаточно знаком с Angular, чтобы полностью понять почему.

Мне удалось создать требуемое поведение, переопределив ChangeDetectionStrategy в моей конфигурации TestBed.

TestBed.configureTestingModule({
    imports: [],
    declarations: [TestComponent],
    providers: []
  })
    .overrideComponent(TestComponent, {
      set: { changeDetection: ChangeDetectionStrategy.Default }
    })
    .compileComponents();
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...