如何在单元测试 Angular 中使用 @input 创建组件?

How to create component with @input on unit tests Angular?

我在创建具有@input 的测试组件时遇到问题。在组件内部,它使用模型反馈中的属性,我在测试文件中进行了导入,但它显示错误。有人可以帮助我吗?

意见反馈-card.component.ts

import { Component, OnInit, Input, HostBinding } from '@angular/core';
import { FeedbackCommentsComponent } from '../feedback-comments/feedback-comments.component';
import { routerAnimation } from '../../../../utils/page.animation';
import { AuthService } from '../../../../services/auth.service';
import { Feedback } from '../../../../models/feedback';
import { FirestoreService } from '../../../../services/firestore.service';
import * as firebase from 'firebase/app';
import 'firebase/firestore';
import { first } from 'rxjs/operators';
import { MatBottomSheet } from '@angular/material/bottom-sheet';
import { MatSnackBar } from '@angular/material/snack-bar';

@Component({
  selector: 'app-feedback-card',
  templateUrl: './feedback-card.component.html',
  styleUrls: ['./feedback-card.component.scss'],
  animations: [routerAnimation]
})

export class FeedbackCardComponent implements OnInit {

  @HostBinding('@routerAnimation') routerAnimation = true;
  @Input() feedback: Feedback
  @Input() isAdmin = false
  input
  userId
...

意见反馈-card.component.spec.ts

import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
import { MatBottomSheet } from '@angular/material/bottom-sheet';
import { MatSnackBar } from '@angular/material/snack-bar';
import { FirestoreService } from '../../../../services/firestore.service';
import { AuthService } from '../../../../services/auth.service';
import { FeedbackCardComponent } from './feedback-card.component';
import { CommonModule } from '@angular/common';
import { Feedback } from '../../../../models/feedback';
import { FormBuilder, FormsModule, ReactiveFormsModule } from '@angular/forms';
import { AppModule } from 'src/app/app.module';
import { MatDialogModule } from '@angular/material/dialog';
import { TranslateFakeLoader, TranslateLoader, TranslateModule, TranslateService } from '@ngx-translate/core';
import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/compiler';
import { FunctionsService } from 'src/app/services/functions.service';
import { MatProgressBarModule } from '@angular/material/progress-bar';
import { Skill } from 'src/app/models/skill';

fdescribe('FeedbackCardComponent', () => {
  let component: FeedbackCardComponent;
  let fixture: ComponentFixture<FeedbackCardComponent>;

  beforeEach(waitForAsync(() => {
    TestBed.configureTestingModule({
        imports: [
          CommonModule,
          ReactiveFormsModule,
          FormsModule,
          AppModule,
          MatDialogModule,
          TranslateModule.forRoot({
              loader: {
                provide: TranslateLoader,
                useClass: TranslateFakeLoader
              }
          })
      ],
      schemas: [
        CUSTOM_ELEMENTS_SCHEMA
      ],
      declarations: [ 
        FeedbackCardComponent,
      ],
      providers: [
        FirestoreService
        MatSnackBar,
        MatProgressBarModule,
        FirestoreService,
        FunctionsService,
        TranslateService,
    ]
    })
    .compileComponents();
  }));

  beforeEach(() => {
    fixture = TestBed.createComponent(FeedbackCardComponent);
    fireStoreServiceMock = TestBed.inject(FirestoreService);
    component = fixture.componentInstance;
    fixture.detectChanges();
  });

  it('should create', () => {
    expect(component).toBeTruthy();
  });
});

这是错误日志

TypeError: Cannot read property 'skill' of undefined
TypeError: Cannot read property 'skill' of undefined
    at FeedbackCardComponent_Template (ng:///FeedbackCardComponent.js:305:52)
    at executeTemplate (http://localhost:9876/_karma_webpack_/webpack:/node_modules/@angular/core/__ivy_ngcc__/fesm2015/core.js:9545:1)
    at refreshView (http://localhost:9876/_karma_webpack_/webpack:/node_modules/@angular/core/__ivy_ngcc__/fesm2015/core.js:9414:1)
    at refreshComponent (http://localhost:9876/_karma_webpack_/webpack:/node_modules/@angular/core/__ivy_ngcc__/fesm2015/core.js:10580:1)
    at refreshChildComponents (http://localhost:9876/_karma_webpack_/webpack:/node_modules/@angular/core/__ivy_ngcc__/fesm2015/core.js:9211:1)
    at refreshView (http://localhost:9876/_karma_webpack_/webpack:/node_modules/@angular/core/__ivy_ngcc__/fesm2015/core.js:9464:1)
    at renderComponentOrTemplate (http://localhost:9876/_karma_webpack_/webpack:/node_modules/@angular/core/__ivy_ngcc__/fesm2015/core.js:9528:1)
    at tickRootContext (http://localhost:9876/_karma_webpack_/webpack:/node_modules/@angular/core/__ivy_ngcc__/fesm2015/core.js:10754:1)
    at detectChangesInRootView (http://localhost:9876/_karma_webpack_/webpack:/node_modules/@angular/core/__ivy_ngcc__/fesm2015/core.js:10779:1)
    at RootViewRef.detectChanges (http://localhost:9876/_karma_webpack_/webpack:/node_modules/@angular/core/__ivy_ngcc__/fesm2015/core.js:22792:1)

第一个 fixture.detectChanges() 调用 ngOnInit 因此请确保在此之前定义您的输入。

试试这个:

beforeEach(() => {
    fixture = TestBed.createComponent(FeedbackCardComponent);
    fireStoreServiceMock = TestBed.inject(FirestoreService);
    component = fixture.componentInstance;
    component.feedback = // mock your feedback
    component.isAdmin = // optional because I see it is set to false, but you can mock it here too.
    fixture.detectChanges();
  });