为什么使用模板驱动的测试会返回未定义的值? [英] Why does testing with template driven return undefined value?

查看:16
本文介绍了为什么使用模板驱动的测试会返回未定义的值?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用 Angular 9 中的模板驱动表单来测试一个简单的表单.我将值插入到输入中并单击提交按钮,该按钮将值发送到服务.代码有效,但测试失败,因为值始终未定义.

I'm trying to test a simple form using template-driven forms in Angular 9. I insert values into the inputs and click on a submit button, which sends the values to a service. The code works, but the test fails because the values always remain undefined.

我已经创建了一个问题的演示在这里展示(我的实际代码会太复杂):

I've created a demo of the problem to show here (my actual code would be too complex):

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.spec.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'.

有人可以帮助我使测试正确填写输入吗?谢谢!

Could someone help me to make the inputs are correctly filled out by the test? Thanks!

推荐答案

我找到了解决方案,虽然我不明白为什么,因为文档没有解释它.

I found the solution, although I don't understand exactly why, since the documentation doesn't explain it.

纠正测试的方法有多种.

There are different ways to correct the test.

在我创建的例子中,需要在fakeAsync中包含测试代码,并分别调用fixture.detectChanges()和tick()函数:

In the example I created, it is necessary to include the test code inside a fakeAsync, and call the fixture.detectChanges() and tick() functions, respectively:

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 中创建了组件(没有异步),这会有所不同.如果在没有 async 的情况下在 beforeEach 中创建组件,则必须在其中使用 fakeAsync,并且不能在此 beforeEach 中调用 fixture.detectChanges() (这就是破坏了我的原始代码的原因).但是,如果您的 beforeEach 具有 async,则不需要使用 fakeAsync,并且在您的测试中使用 async 或 fakeAsync (it) 是可选的.

I need to mention that my original code creates the component inside a beforeEach (without async), and that makes a difference. If you create the component inside a beforeEach without async, you must use fakeAsync in it, and you CANNOT call fixture.detectChanges() inside this beforeEach (that was what broke my original code). However, if your beforeEach has async, the use of fakeAsync is unnecessary, and using async or fakeAsync in your test (it) is optional.

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

    fixture.detectChanges();
}));

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

这篇关于为什么使用模板驱动的测试会返回未定义的值?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆