首页 > 解决方案 > 如何在 Jasmine 的构造函数中测试依赖于私有参数的方法

问题描述

我根本没有编辑组件文件的权限,所以这不是一个选项。我必须测试一个依赖私有变量才能成功运行的方法。

  candidateSmartMatch(): void {
    const jobAddressFormGroup = this.locationModel.formGroup.get('JobAddress');
    if (!!jobAddressFormGroup) {
      this.subs.sink = jobAddressFormGroup.valueChanges.pipe(
        debounceTime(2000),
        filter((value: PostLocationInterface) => !!value.CityState || !!value.Zip)
      ).subscribe(
        (value: PostLocationInterface) => {
          const formattedAddress = this.formatAddress({
            StreetAddress1: value.StreetAddress1,
            StreetAddress2: value.StreetAddress2,
            CityState: value.CityState,
            Zip: value.Zip,
            DispCity: ''
          });
          this.candidateSmartMatchManagementService.setJobLocation(formattedAddress);
          this.jobCompetitionService.setLocation(formattedAddress);
        });
    }
  }

变量this.locationModel来自构造函数,它作为私有参数输入。有一种initialize()方法可以像这样设置公共变量form

this.form = this.locationModel.formGroup;

如果我能在单元测试中得到 的值this.form,那可能会解决我的问题,但调用component.initialize()似乎并没有什么不同。我也尝试在我的测试中创建一个模拟表单。这是我的测试:

  it('call setJobLocation method', fakeAsync(() => {
    spyOn(candidateSmartMatchManagementService, 'setJobLocation');
    component.initialize();
    component.form = new FormGroup({
      StreetAddress1: new FormControl('Street1'),
      StreetAddress2: new FormControl('Street2'),
      CityState: new FormControl('Miami, FL'),
      Zip: new FormControl('33015'),
      FormattedAddress: new FormControl('Street1 Street2 Miami, FL 33015')
    });
    component.candidateSmartMatch();
    expect(candidateSmartMatchManagementService.setJobLocation).toHaveBeenCalled();
  }));

基本上,我只是想测试一个方法candidateSmartMatch成功调用方法的场景setJobLocation。我正在使用一个模拟服务candidateSmartMatchManagementService,但它包含一个模拟方法setJobLocation

编辑:

我更改了我的测试方法以按照建议使用 locationModel 模拟,但它仍然说“预期的间谍 setJobLocation 已被调用”

  it('call setJobLocation method', fakeAsync(() => {
    spyOn(candidateSmartMatchManagementService, 'setJobLocation');
    jobLocationModel.formGroup = new FormGroup({
      StreetAddress1: new FormControl('Street1'),
      StreetAddress2: new FormControl('Street2'),
      CityState: new FormControl('Miami, FL'),
      Zip: new FormControl('33015'),
      FormattedAddress: new FormControl('Street1 Street2 Miami, FL 33015')
    });
    component.candidateSmartMatch();
    expect(candidateSmartMatchManagementService.setJobLocation).toHaveBeenCalled();
  }));

这是我的模型模拟:

export class JobLocationModelMock {
  formGroup = new FormGroup({
    JobAddressID: new FormControl('test'),
    JobRelocation: new FormControl(),
    FormattedAddress: new FormControl(),
    JobAddress : new FormGroup({
      JobRelocation: new FormControl(),
      CityState: new FormControl(),
      Zip: new FormControl(),
      StreetAddress1: new FormControl('test'),
      StreetAddress2: new FormControl(),
      DispCity: new FormControl()
    }),
    JobAddresses: new FormArray([])
  });
  private model: PostJobService = new PostJobService();
  init(): Observable<any> { return Observable.of([]); }

  defineModel() {
    return;
  }
}

标签: angularunit-testingjasmine

解决方案


如果我理解正确,您将通过当前组件的构造函数发送 locationModel 。如果是这种情况,那么您可以在设置 TestBed 期间传递一个模拟模型。在没有看到您的设置代码的情况下,我将举个例子。

beforeEach(async(() => {
    TestBed.configureTestingModule({
      providers: [
        {
          provide: LocationModel, useValue: MockLocationModel
        }
      ],
      declarations: [Component]
    })
      .compileComponents();
  }));

就使测试工作而言,它看起来好像您有一个侦听器正在检查表单中的值更改。在某些时候,您只需要在调用component.candidateSmartMatch();测试后在表单中设置/更新一些值。


推荐阅读