angular2单元测试未检测到输入变化

时间:2017-01-25 02:04:29

标签: unit-testing angular karma-runner karma-jasmine

我的问题与How do I trigger a ngModel model update in an Angular 2 unit test?

完全相同

我必须在考试中做些傻事。任何人都可以指出我忽视的任何明显错误

组件

    @Component({
  moduleId: module.id,
  selector: 'od-tree',
  templateUrl: 'tree.component.html',
  styleUrls: ['tree.component.css'],
  changeDetection: ChangeDetectionStrategy.OnPush
})
export class TreeComponent implements OnInit, OnChanges, AfterViewChecked {
  @Input() allResources: { items: {} };
  @Input() resourceGroups = { items: {} };
  @Input() selectedNodes: ITree.SelectedNode[];
  @Input() showIcons: boolean;
  @Input() showCheckboxes: boolean;
  @Input() omitAncillaryDBs: boolean;

  @Output() selectNode = new EventEmitter<any>();

  searchResource$ = new Subject<string>();
  searchField = '';
  tabs = [
    { title: TABS.ALL_RESOURCES, active: true },
    { title: TABS.RESOURCE_GROUPS, active: false }
  ];
  inSearchMode = false;
  trees = {
    ALL_RESOURCES: {
      searchText: null,
      tree: []
    },
    RESOURCE_GROUPS: {
      searchText: null,
      tree: []
    }
  };

  private _allResourcesTreeState = [];
  private _resourceGroupsTreeState = [];
  private ancillaryDBList = ['App-Services', 'Documents', 'Extensions', 'Fab', 'Last-Login',
    'Meters', 'Modules', 'Schemas', 'Security', 'Triggers'];

  constructor(private _cd: ChangeDetectorRef) { }
...
...
...
}

模板

<div class="input-with-icon">
        <i class="icon-search"></i>
        <input type="text" [(ngModel)]="searchField" name="searchField" class="form-control" id="search-resources" placeholder="Search" (ngModelChange)="searchResource$.next(searchField)">
      </div>
... (truncated)
....
....

单元测试

 describe('tree component', () => {
    //let activatedRoute: ActivatedRouteStub;
    let comp: TreeComponent;
    let fixture: ComponentFixture<TreeComponent>;
    let de: DebugElement;
    let el: HTMLElement;


    beforeEach(async(() => {
      TestBed.configureTestingModule({
        imports: [TreeModule],
      })
        .compileComponents();
    }));

    beforeEach(() => {
      fixture = TestBed.createComponent(TreeComponent);
      comp = fixture.componentInstance;
      de = fixture.debugElement;
      el = de.nativeElement;
      comp.ngOnInit();
      fixture.detectChanges();
    });


    it('should bind value to ngmodel',() => {
         let inputEl = de.query(By.css('input#search-resources'))
         inputEl.nativeElement.value = 'node';
         inputEl.triggerEventHandler('input', {target: inputEl.nativeElement});
         fixture.detectChanges();
         expect(comp.searchField).toEqual('node');
      });  

 // another approach 
   it('should filter resources when used in host component',fakeAsync(() => {
       let inputEl = de.query(By.css('input#search-resources'));
       inputEl.nativeElement.value = 'node';
       dispatchEvent('input', inputEl.nativeElement);
       tick();
       fixture.detectChanges();
       expect(de.queryAll(By.css('li.host-leaf:not([hidden])')).length).toEqual(2, 'should show filtered hosts');
    }));

    }

2 个答案:

答案 0 :(得分:4)

当与OnPush更改检测策略结合使用时,这是当前Testbed实现detectChanges()的已知错误。你可以在这里读更多关于它的内容。非常讨厌。

事实证明@Input更改不是从当前组件本身触发,而是从父组件触发。

以下是我使用angular v2.4

进行测试的方法
fixture.changeDetectorRef['internalView']['compView_0'].markAsCheckOnce();
fixture.detectChanges();

https://github.com/angular/angular/issues/12313

答案 1 :(得分:0)

您需要将 FormsModule 导入测试模块,以使ngModel绑定正常工作。

beforeEach(async(() => {
  TestBed.configureTestingModule({
    imports: [
    TreeModule
    FormsModule
    ]
  })
    .compileComponents();
}));