2017-12-31 380 views
1

내 구성 요소에 템플릿 기반 폼을 단위 테스트하려고합니다. 이 양식은 간단하고 사람의 연락처 정보가 들어 있습니다. 내가 뭘하려고하는지 단위 테스트 다양한 유효성 검사 시나리오입니다. 내가 할 수있는 일은 단순히 전자 메일 주소에 값을 설정 한 다음 ngForm 개체를 검사하고 emailAddress에 대한 formControl을 가져온 다음 유효성 상태를 확인하는 것입니다. 그러나, 내가 발견 한 것은 폼이 존재하지만 컨트롤을 전혀 포함하지 않는다는 것입니다. 따라서 양식이 완전히 만들어지지 않은 것으로 보입니다.구성 요소에서 단위 테스트 템플릿 기반 폼을 시도하는 중 폼에 컨트롤이 없습니다

코드 (간결을위한 I는 생략했습니다 가져 오기 및 일부 업체 문 ​​등) :

사람 - 세부 사항 - 접촉 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()"을 수행해야합니다. 예를 들면 다음과 같습니다.

구성 요소가 분명히 "안정적이지 않은"실제 응용 프로그램 내에서 비슷한 문제가 발생했기 때문에 이것은 흥미 롭습니다. 양식 내의 formControl을 즉시 액세스 (OnInit 또는 AfterViewInit 내에서)하려고하면 null 객체가됩니다.