2017-12-31 33 views
1

私のコンポーネントにテンプレートベースのフォームをユニットテストしようとしています。フォームは簡単で、人の連絡先情報を含んでいます。私がしようとしているのは、単体テストのさまざまな検証シナリオです。私ができることは、単にemail-addressに値を設定してからngFormオブジェクトを調べ、emailContextのformControlを取得し、有効性のステータスを確認することだと思いました。しかし、私が見つけているのは、フォームは存在しますが、コントロールはまったく含まれていないということです。だから、フォームは完全に構築されていないようです。コンポーネントでテンプレートテスト用のフォームテストを行うと、フォームにコントロールがありません

コード(私は簡潔にするため、インポートおよび一部のプロバイダ文などを省略しました):

人-詳細-接触info.component.html

<custom-input type="text" 
      name="emailAddress" 
      [(ngModel)]="model.emailAddress" 
      maxlength="255" 
      pattern="^[^\[email protected]][email protected][^\[email protected]]+\.[^\[email protected]]{2,}$" 
      #emailAddress="ngModel"> 
</custom-input> 

<custom-input type="text" 
      [disabled]="permissions.canViewOnly" 
      name="phone" 
      [(ngModel)]="model.phone" 
      maxlength="16"> 
</custom-input> 

<custom-input type="text" 
      [disabled]="permissions.canViewOnly" 
      name="model.fax" 
      [(ngModel)]="fax" 
      maxlength="16"> 
</custom-input> 

人-詳細 - コンタクト-info.component.ts

@Component({ 
    selector: 'person-details-contact-info', 
    templateUrl: 'person-details-contact-info.component.html', 
    viewProviders: [{ provide: ControlContainer, useExisting: NgForm }] 
}) 
export class PersonDetailsContactInfoComponent { 

    @Input('model') 
    model: { 
     emailAddress: '', 
     phone: '', 
     fax: '' 
    } 
} 

**ユニットテストコード**

@Component({ 
    template: ` 
     <form #form="ngForm"> 
      <person-details-contact-info [(model)]="model"> 
      </person-details-contact-info> 
     </form> 
    `, 
    providers: [ ] 
}) 
export class TestHostComponent { 
    model: PersonDetailsContactInfoModel = new PersonDetailsContactInfoModel(); 

    @ViewChild('form') 
    ngForm: NgForm; 
} 

describe('In the file "person-details-contact-info.component.ts',() => { 

    let fixture: ComponentFixture<TestHostComponent>; 
    let component: TestHostComponent; 

    beforeEach(() => { 
     TestBed.configureTestingModule({ 
      imports: [FormsModule, NoopAnimationsModule], 
      declarations: [TestHostComponent, PersonDetailsContactInfoComponent], 
      providers: [ ] 
     }); 

     fixture = TestBed.createComponent(TestHostComponent); 
     component = fixture.componentInstance; 
    }); 

    it('is has invalid email format',() => { 
     component.model.emailAddress = 'an invalid email format.'; 
     fixture.detectChanges(); 

     const ctrl = component.ngForm.form.get('emailAddress'); 
     expect(ctrl.valid).toBe(false); 
    }); 
}); 

"ctrl"オブジェクトがnullであるため、上記のテストは間違っています。 emailAddressコントロールがフォーム内に存在しません。ちなみに、これは実際のコンポーネントですべて正常に動作しますので、私はユニットテストのセットアップに何か間違っています。

最後に、コードを理解するために、私のアプリは私が非常に大きなフォームを別々のコンポーネントに分割した方法です。したがって、この「連絡先情報」コンポーネントは、はるかに大きな形式のセクションです。そのため、私はモデルにバインドして、person-details-contact-info.componentのprovidersセクションに既存のNgFormを提供しています。繰り返しますが、すべてがアプリケーション自体の中で完璧に機能します。私が単体テストをしようとしている方法は、私が期待した通りに動作していないことです。

答えて

0

さて、私は何が起こっているのか把握しました。私がしようとしているのは動作しますが、単体テストの "it"ブロック内で "fixture.detectChanges()"の後に "fixture.whenStable()"を実行する必要があります。例:

it('is has invalid email format',() => { 
    component.model.emailAddress = 'an invalid email format.'; 
    fixture.detectChanges(); 

    fixture.whenStable().then(() => { 
     const ctrl = component.ngForm.form.get('emailAddress'); 
     expect(ctrl.valid).toBe(false); 
    });   
}); 

コンポーネントが明らかに「安定」していない実際のアプリ内で同様の問題が発生したため、これは興味深いものです。フォーム内ですぐに(OnInitまたはAfterViewInit内で)formControlsにアクセスしようとすると、nullオブジェクトが返されます。

関連する問題