Почему тестирование на основе шаблонов возвращает неопределенное значение? - PullRequest
1 голос
/ 02 апреля 2020

Я пытаюсь протестировать простую форму с использованием шаблонно-управляемых форм в Angular 9. Я вставляю значения во входные данные и нажимаю кнопку отправки, которая отправляет значения в службу. Код работает, но тест не пройден, потому что значения всегда остаются неопределенными.

Я создал демонстрацию проблемы, чтобы показать ее здесь (мой фактический код будет слишком сложным):

app.component.ts

@Component({
  selector: 'app-root',
  template: `
    <form #f="ngForm" (ngSubmit)="submit(f)">

      <input type="text" ngModel name="field1">
      <input type="text" [(ngModel)]="field2" name="field2">

      <input type="submit" value="submit">

      <br>field1: {{ f.value.field1 }}
      <br>submitedText: {{ submitedText }}
      <br>field2: {{ field2 }}

    </form>
  `
})
export class AppComponent {
  public submitedText: string;
  public field2: string;

  public submit(form: NgForm) {
    this.submitedText = form.value.field1;
  }
}

app.component.spe c .ts

describe('AppComponent', () => {
  it('shoud to submit the text', () => {
    const fixture = TestBed.configureTestingModule({
      declarations: [ AppComponent ],
      imports: [ FormsModule ],
    }).createComponent(AppComponent)

    fixture.detectChanges();

    const field1 = fixture.elementRef.nativeElement.querySelector('input[name="field1"]');
    const field2 = fixture.elementRef.nativeElement.querySelector('input[name="field2"]');
    const button = fixture.elementRef.nativeElement.querySelector('input[type="submit"]');

    field1.value = 'test 1';
    field2.value = 'test 2';
    field1.dispatchEvent(newEvent('input'));
    field2.dispatchEvent(newEvent('input'));
    fixture.detectChanges();

    button.click();
    fixture.detectChanges();

    expect(fixture.componentInstance.submitedText).toBe('test 1');
    expect(fixture.componentInstance.field2).toBe('test 2');
  });
});
export function newEvent(eventName: string, bubbles = false, cancelable = false) {
  const evt = document.createEvent('CustomEvent');  // MUST be 'CustomEvent'
  evt.initCustomEvent(eventName, bubbles, cancelable, null);
  return evt;
}

Результат:

Failures
AppComponent > shoud to submit the text
Expected undefined to be 'test 1'.
Expected undefined to be 'test 2'.

Может ли кто-нибудь помочь мне сделать так, чтобы входные данные были правильно заполнены тестом? Спасибо!

1 Ответ

1 голос
/ 02 апреля 2020

Я нашел решение, хотя точно не понимаю, почему, поскольку документация не объясняет его.

Существуют различные способы исправить тест.

В примере Я создал, необходимо включить тестовый код в fakeAsyn c и вызвать функции fixture.detectChanges () и tick () соответственно:

describe('AppComponent', () => {
  it('shoud to submit the text', fakeAsync(() => {
    const fixture = TestBed.configureTestingModule({
      declarations: [ AppComponent ],
      imports: [ FormsModule ],
    }).createComponent(AppComponent)

    fixture.detectChanges();
    tick();

    // rest of the code ...
}));


Я должен отметить, что мой оригинал Код создает компонент внутри beforeEach (без asyn c), и это имеет значение. Если вы создаете компонент внутри beforeEach без asyn c, вы должны использовать в нем fakeAsyn c, и вы НЕ МОЖЕТЕ вызывать fixture.detectChanges () внутри beforeEach (именно это сломало мой исходный код). Однако, если ваш beforeEach имеет asyn c, использование fakeAsyn c не является необходимым, и использование asyn c или fakeAsyn c в вашем тесте (оно) является необязательным.

beforeEach(async(() => {
    const fixture = TestBed.configureTestingModule({
      declarations: [ AppComponent ],
      imports: [ FormsModule ],
    }).createComponent(AppComponent)

    fixture.detectChanges();
}));

it('shoud to submit the text', () => {
// rest of the code ...
...