Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
1.1k views
in Technique[技术] by (71.8m points)

typescript - Angular 2 unit testing component, mocking ContentChildren

I am implementing a wizard component in Angular 2 RC4, and now I am trying to write som unit tests. Unit testing in Angular 2 is starting to get well documented, but I simply cannot find out how to mock the result of a content query in the component.

The app has 2 components (in addition to the app component), WizardComponent and WizardStepComponent. The app component (app.ts) defines the wizard and the steps in its template:

 <div>
  <fa-wizard>
    <fa-wizard-step stepTitle="First step">step 1 content</fa-wizard-step>
    <fa-wizard-step stepTitle="Second step">step 2 content</fa-wizard-step>
    <fa-wizard-step stepTitle="Third step">step 3 content</fa-wizard-step>
  </fa-wizard>
</div>

The WizardComponent (wizard-component.ts) gets a reference to the steps by using a ContentChildren query.

@Component({
selector: 'fa-wizard',
template: `<div *ngFor="let step of steps">
            <ng-content></ng-content>
          </div>
          <div><button (click)="cycleSteps()">Cycle steps</button></div>`

})
export class WizardComponent implements AfterContentInit {
    @ContentChildren(WizardStepComponent) steps: QueryList<WizardStepComponent>;
....
}

The problem is how to mock the steps variable in the unit test:

describe('Wizard component', () => {
  it('should set first step active on init', async(inject([TestComponentBuilder], (tcb: TestComponentBuilder) => {
    return tcb
    .createAsync(WizardComponent)
    .then( (fixture) =>{
        let nativeElement = fixture.nativeElement;
        let testComponent: WizardComponent = fixture.componentInstance;

        //how to initialize testComponent.steps with mock data?

        fixture.detectChanges();

        expect(fixture.componentInstance.steps[0].active).toBe(true);
    });
  })));
});

I have created a plunker implementing a very simple wizard demonstrating the problem. The wizard-component.spec.ts file contains the unit test.

If anyone can point me in the right direction, I would greatly appreciate it.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Thanks to drewmoore's answer in this question, I have been able to get this working.

The key is to create a wrapper component for testing, which specifies the wizard and the wizard steps in it's template. Angular will then do the content query for you and populate the variable.

Edit: Implementation is for Angular 6.0.0-beta.3

My full test implementation looks like this:

  //We need to wrap the WizardComponent in this component when testing, to have the wizard steps initialized
  @Component({
    selector: 'test-cmp',
    template: `<fa-wizard>
        <fa-wizard-step stepTitle="step1"></fa-wizard-step>
        <fa-wizard-step stepTitle="step2"></fa-wizard-step>
    </fa-wizard>`,
  })
  class TestWrapperComponent { }

  describe('Wizard component', () => {
    let component: WizardComponent;
    let fixture: ComponentFixture<TestWrapperComponent>;

    beforeEach(async(() => {
      TestBed.configureTestingModule({
        schemas: [ NO_ERRORS_SCHEMA ],
        declarations: [
          TestWrapperComponent,
          WizardComponent,
          WizardStepComponent
        ],
      }).compileComponents();
    }));

    beforeEach(() => {
      fixture = TestBed.createComponent(TestWrapperComponent);
      component = fixture.debugElement.children[0].componentInstance;
    });

    it('should set first step active on init', () => {
      expect(component.steps[0].active).toBe(true);
      expect(component.steps.length).toBe(3);
    });
  });

If you have better/other solutions, you are very welcome to add you answer as well. I'll leave the question open for some time.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...