【问题标题】:Unit Testing in Angular, Test Component is undefinedAngular中的单元测试,测试组件未定义
【发布时间】:2019-03-26 09:47:38
【问题描述】:

我正在尝试在 Angular 6 中对“添加对象”(添加菜)组件进行单元测试。使用我当前的代码,我收到错误 “无法读取未定义的属性 'dishForm'”。

那么,似乎 DishAddComponent 没有被识别为要测试的组件?有人可以帮我解决这个问题吗?提前致谢!

我还尝试(以及其他)将异步添加到 beforeEach,如下所述:Angular 2 Testing - Component Instance is undefined,但它不起作用。

要进行单元测试的 Angular 组件:

export class DishAddComponent implements OnInit {
  public dishForm: FormGroup;

  constructor(private dishService: DishService,
    private formBuilder: FormBuilder,
    private router: Router) { }

  ngOnInit() {
    // define dishForm (with empty default values)
    this.dishForm = this.formBuilder.group({
      name: ['', [Validators.required, Validators.maxLength(30), Validators.pattern('[a-zA-Z :]*')]],
      country: [''],
      ingredients: this.formBuilder.array([]),
      recipe: ['', [Validators.required, Validators.minLength(50)]],
    }, { validator: CustomValidators.DishNameEqualsCountryValidator });
  }

  addIngredient(): void {
    let ingredientsFormArray = this.dishForm.get('ingredients') as FormArray;
    ingredientsFormArray.push(IngredientSingleComponent.createIngredient());
  }

  addDish(): void {
    if (this.dishForm.dirty && this.dishForm.valid) {

      let dish = this.dishForm.value;

      this.dishService.addDish(dish)
        .subscribe(
          () => {
            this.router.navigateByUrl('/dishes');
          });
    }
  }
}

Jest 中的单元测试:

describe('DishAddComponent', () => {
  let component: DishAddComponent;
  let fixture: ComponentFixture<DishAddComponent>;
  let formGroup: FormGroup;
  let formBuilderMock: any;
  let dishServiceMock: any;

  beforeEach(() => {
      formBuilderMock = {
      group: jest.fn().mockName('formBuilderMock.group'),
      array: jest.fn().mockName('formBuilderMock.array')
    };

    dishServiceMock = {
      addDish: jest.fn().mockName('dishServiceMock.addDish')
    };

    TestBed.configureTestingModule({
      imports: [ ReactiveFormsModule, FormsModule, RouterTestingModule.withRoutes(routes)],
      declarations: [ DishAddComponent, IngredientSingleComponent ],
      providers: 
      [ 
        { provide: FormBuilder, useValue: formBuilderMock },
        { provide: FormGroup, useValue: formGroup },
        { provide: DishService, useValue: dishServiceMock }
      ]
    });
    fixture = TestBed.createComponent(DishAddComponent);
    component = fixture.componentInstance;
    fixture.detectChanges();
  });

  it('form invalid when empty', () => {
    (console).log(component);
  expect(component.dishForm.valid).toBeFalsy();
 });
});

编辑: 如果我使用下面的代码,我也会收到错误:

DishAddComponent › 应该创建

期望(收到).toBeTruthy()

收到:未定义

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

【问题讨论】:

  • 尝试使用默认测试,即should create → expect(component).toBetruhty();。看看它是否有效。另外,请发布您面临的错误。
  • 感谢您的快速回复!我已经编辑了我的问题。如果我将其更改为默认测试,我会收到以下错误: ● DishAddComponent › 应该创建 ● expect(received).toBeTruthy() ● Received: undefined

标签: angular unit-testing undefined


【解决方案1】:

最后我用下面的代码摆脱了“未定义的错误”。我需要模拟其中一个子组件并创建一个表单构建器实例。感谢您的提示!

describe('DishAddComponent', () => {
  let component: DishAddComponent;
  let fixture: ComponentFixture<DishAddComponent>;
  let dishServiceMock: any;

  // mock singleingredientcomponent
  @Component({
    selector: 'app-ingredient-single',
    template: '<div></div>',
  })
  class MockSingleIngredientComponent {
  @Input() public ingredientIndex: number;
  @Input() public ingredient: FormGroup;
  }

  // create new instance of FormBuilder
  const formBuilder: FormBuilder = new FormBuilder();

  beforeEach(async(() => {
    dishServiceMock = {
      addDish: jest.fn().mockName('dishServiceMock.addDish'),
      addIngredient: jest.fn().mockName('dishServiceMock.addIngredient')
    };

    TestBed.configureTestingModule({
      imports: [ ReactiveFormsModule, FormsModule, RouterTestingModule.withRoutes([])],
      declarations: [ DishAddComponent, MockSingleIngredientComponent ],
      providers: 
      [ 
        { provide: FormBuilder, useValue: formBuilder },
        { provide: DishService, useValue: dishServiceMock }
      ]
    })
    .compileComponents();
  }));

  beforeEach(() => {
    // create component and test fixture
    fixture = TestBed.createComponent(DishAddComponent);

    // get test component from the fixture
    component = fixture.componentInstance;

    // ..
    fixture.detectChanges();
  });

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

【讨论】:

    【解决方案2】:

    尝试在configureTestingModule()后加入compileComponents()来编译组件

    TestBed.configureTestingModule({
      imports: [ ReactiveFormsModule, FormsModule, RouterTestingModule.withRoutes(routes)],
      declarations: [ DishAddComponent, IngredientSingleComponent ],
      providers: 
      [ 
        { provide: FormBuilder, useValue: formBuilderMock },
        { provide: FormGroup, useValue: formGroup },
        { provide: DishService, useValue: dishServiceMock }
      ]
    })
      .compileComponents();
    

    【讨论】:

    • 谢谢!但不幸的是,如果我尝试这个,我会收到同样的错误
    • 好吧,我没有看到你在测试中实例化 formGroup 的位置。
    • 我试过把它放在提供者中:{提供:FormGroup,useValue:formGroup},我应该如何/在哪里实例化它?
    • 把它放在提供者中是对的,但变量只声明为let formGroup: FormGroup;。它不是对象的实例。您可以在 beforeEach 中添加类似 formGroup = formBuilderMock.group(); 的内容
    • 我添加了 formGroup = formBuilderMock.group();就在测试床之前。这也不能解决我的问题。我确实已经使用了 formBuilderMock = { group: jest.fn().mockName('formBuilderMock.group'),这还不够吗?如果您有其他解决方案,请告诉我!否则,非常感谢您的宝贵时间!
    猜你喜欢
    • 2018-09-02
    • 1970-01-01
    • 2023-02-17
    • 1970-01-01
    • 1970-01-01
    • 2021-04-03
    • 1970-01-01
    • 2021-01-05
    • 1970-01-01
    相关资源
    最近更新 更多