简体   繁体   English

如何在单元测试中注入 Input()?

[英]How to inject Input() in unit testing?

So i try to do some unit testing on a component.所以我尝试对一个组件进行一些单元测试。 But I have some problems with Input() parameter.但是我对 Input() 参数有一些问题。 And then especially a component in the component然后特别是组件中的一个组件

SO I have this component:所以我有这个组件:


export class EcheqDisplayComponent implements OnInit {
  echeq: EcheqSubmissionApi;


  constructor(
    private route: ActivatedRoute
  ) {
    this.echeq = this.route.snapshot.data['submission'];
  }

  ngOnInit() {
  }

  getAnswers(page: EcheqPageApi): any[] {
    return page.elements.map(element => this.echeq.answers[element.name]);
  }
}

and the template:和模板:


<div class="echeq-display" *ngIf="echeq">
  <header class="echeq-display-header header">
    <div class="echeq-display-info">
      <h1 class="heading echeq-display-heading">
        {{ echeq.definition.title }}
      </h1>
      <div class="sub-heading echeq-display-subheading">
        <span class="echeq-display-creator">
          Toegekend door:
          {{ echeq.assignedByProfName ? echeq.assignedByProfName : 'Het Systeem' }}
        </span>
        <span class="echeq-display-date">{{
          echeq.definition.createdOnUtc | date: 'dd MMM'
        }}</span>
      </div>
    </div>
    <app-meta-box
      [metadata]="{
        numPages: echeq.definition.numPages,
        vPoints: echeq.definition.awardedVPoints
      }"
    ></app-meta-box>
  </header>
  <main class="echeq-display-questions body">
    <app-echeq-question
      *ngFor="let page of echeq.definition.pages; let i = index"
      [page]="page"
      [readonly]="true"
      [number]="i + 1"
      [answers]="getAnswers(page)"
    ></app-echeq-question>
  </main>
</div>


and the unit test:和单元测试:


import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { EcheqDisplayComponent } from './echeq-display.component';
import { ParticipantEcheqModule } from '../../participant-echeq.module';
import { RouterModule, ActivatedRoute } from '@angular/router';
import { MockActivatedRoute } from 'src/app/shared/mocks/MockActivatedRoute';
import { MetaData } from '../meta-box/meta-box.component';

describe('EcheqDisplayComponent', () => {
  let component: EcheqDisplayComponent;
  let fixture: ComponentFixture<EcheqDisplayComponent>;
  const metaData: MetaData = new MetaData();
  // const metaDataInfo = fixture.debugElement.componentInstance;


  beforeEach(async(() => {
    TestBed.configureTestingModule({
      declarations: [ ],
      providers: [
        { provide: ActivatedRoute, useClass: MockActivatedRoute }
      ],
      imports:[
        ParticipantEcheqModule

      ]
    })
    .compileComponents();
  }));

  beforeEach(() => {
    fixture = TestBed.createComponent(EcheqDisplayComponent);
    component = fixture.componentInstance;
    fixture.detectChanges();
  });

  fit('should create component', () => {
    metaData.numPages = 20;
    expect(component).toBeTruthy();
  });
});



But it stay saying:但它一直在说:

TypeError: Cannot read property 'numPages' of undefined. TypeError:无法读取未定义的属性“numPages”。

So what I have to change that it is working?那么我必须改变它的工作原理吗?

Thank you谢谢

So the MetaData is from the app-meta-box component.it looks like this:所以 MetaData 来自 app-meta-box 组件。它看起来像这样:


export class MetaData {
  numPages: number;
  vPoints: number;
}

@Component({
  selector: 'app-meta-box',
  templateUrl: './meta-box.component.html',
  styleUrls: ['./meta-box.component.scss']
})
export class MetaBoxComponent implements OnInit {
  @Input() metadata: MetaData;

  constructor() {}

  ngOnInit() {}

}


This is the mock class:这是模拟 class:

export class MockActivatedRoute {
  public snapshot = {
      data: {
         submission: {
           answers: {}
         }
      }
  };
}

I have it now like this:我现在有这样的:

import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { EcheqDisplayComponent } from './echeq-display.component';
import { ParticipantEcheqModule } from '../../participant-echeq.module';
import { RouterModule, ActivatedRoute } from '@angular/router';
import { MockActivatedRoute } from 'src/app/shared/mocks/MockActivatedRoute';
import { MetaData } from '../meta-box/meta-box.component';

describe('EcheqDisplayComponent', () => {
  let component: EcheqDisplayComponent;
  let fixture: ComponentFixture<EcheqDisplayComponent>;
  const metaData: MetaData = new MetaData();
  // const metaDataInfo = fixture.debugElement.componentInstance;


  beforeEach(async(() => {
    TestBed.configureTestingModule({
      declarations: [ ],
      providers: [
        { provide: ActivatedRoute, useValue: new MockActivatedRoute().withData({submission:{ answers:{} } }) }
      ],
      imports:[
        ParticipantEcheqModule
      ]
    })
    .compileComponents();
  }));

  beforeEach(() => {
    fixture = TestBed.createComponent(EcheqDisplayComponent);
    component = fixture.componentInstance;
    fixture.detectChanges();
  });

  fit('should create component', () => {
    component.echeq = {
      definition: {
        title: 'test title',
        awardedVPoints: 0,
        numPages: 9
      }
   }
    expect(component).toBeTruthy();
  });
});

But then I get this error:


Property 'answers' is missing in type '{ definition: { title: string; awardedVPoints: number; numPages: number; }; }' but required in type 'EcheqSubmissionApi'.ts(2741)
echeqSubmissionApi.ts(59, 5): 'answers' is declared here.

I have it now like this:我现在有这样的:

fit('should create component', () => {
    component.echeq = {
      definition: {
        title: 'test title',
        awardedVPoints: 0,
        numPages:9
      }
    } as EcheqSubmissionApi;
    expect(component).toBeTruthy();
  });
export interface EcheqSubmissionApi { 
    /**
     * Primary key of this submission (server set).
     */
    id?: string;
    definition?: EcheqDefinitionApi;
    /**
     * Id of the prof who assigned this eCheq (server set).
     */
    assignedByProfId?: string;
    /**
     * Name of the prof who assigned this eCheq (server set). Only set on get operations. May be null if assigned by the system.
     */
    assignedByProfName?: string;
    /**
     * Id of the organisation who assigned this eCheq (server set).
     */
    assignedByOrgId?: number;
    /**
     * Participant ID of the patient this eCheq is assigned to (server set).
     */
    assignedToId?: string;
    /**
     * When this submission was assigned (UTC, server set).
     */
    assignedOnUtc?: Date;
    /**
     * If set until when the eCheq can be submitted.
     */
    validUntilUtc?: Date;
    /**
     * Whether the eCheq has been started and whether it has been submitted (server set).
     */
    status?: EcheqSubmissionApi.StatusEnum;
    /**
     * When this submission was completed (UTC, server set).
     */
    submittedOnUtc?: Date;
    /**
     * Answers of form.  In the form of a json object with name and value of the questions  {      \"nameOfQuestion\" : \"valueOfQuestion\"  }
     */
    answers: object;
    /**
     * initialValues of form.  In the form of a json object with name and value of variables  {      \"nameOfQuestion\" : \"valueOfQuestion\"  }
     */
    initialValues?: object;
    /**
     * The page the participant is currently on
     */
    currentPage?: number;
    /**
     * The progress of the echeq in percentage
     */
    progress?: number;
}
export namespace EcheqSubmissionApi {
    export type StatusEnum = 'New' | 'Active' | 'Submitted';
    export const StatusEnum = {
        New: 'New' as StatusEnum,
        Active: 'Active' as StatusEnum,
        Submitted: 'Submitted' as StatusEnum
    };
}

But if I run the unit test, I still get this error:但是,如果我运行单元测试,我仍然会收到此错误:

TypeError: Cannot read property 'numPages' of undefined

To answer your question:要回答您的问题:

component.metadata = /// whatever you want this to be

You have your error with numPages: echeq.definition.numPages .您对numPages: echeq.definition.numPages有错误。 Endeed, echeq is also undefined. Endeed, echeq也是未定义的。

You can try:你可以试试:

component.echeq = {
   definition: {
     numPages: 9
   }
}

Or better way would be to returns this value from this.route.snapshot.data['submission'];或者更好的方法是从this.route.snapshot.data['submission'];返回这个值。 so from MockActivatedRoute所以从MockActivatedRoute

UPDATE :更新

And update MockActivatedRoute to allows dynamic parameters:并更新MockActivatedRoute以允许动态参数:

export class MockActivatedRoute {
  snapshot = {
      data: {}
  };

  constructor(){}

  withData(data:any): MockActivatedRoute {
     this.snapchot.data = data;
     return this;
 }
}

So now in your test, you can use it:所以现在在你的测试中,你可以使用它:

{ provide: ActivatedRoute, useValue: new MockActivatedRoute().withData({submission:{ answers:{} } }) }

No problem.没问题。 It was an easy:这很容易:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM