0

在 Angular 的ControlValueAccessor接口中,定义了以下方法:

registerOnChange(fn: any): void;

在测试实现的组件时ControlValueAccessor,我需要断言传递给的最新参数值fnregisterOnChange预期值。请注意,我不是为fn自己断言值,而是传递给的参数值fn传递给registerOnChange

我该怎么做?

我正在尝试这些方面的东西,但它似乎没有奏效。在我预计它会失败的情况下,测试“通过”。

...
scenarioArray.forEach((scenario) => {
  it(`changing control value should return correct date value`, fakeAsync(() => {
    // arrange
    component.writeValue(scenario.writtenControlValue);

    // act
    fixture.detectChanges();
    fixture.whenStable().then(() => {
      const input = fixture.debugElement.query(By.css('input')).nativeElement;
      input.value = scenario.newControlValue;
      input.dispatchEvent(new Event('input'));

      // TODO (below not working): assert expectedResult is passed to fn passed to registerOnChange
      spyOn(component, 'registerOnChange').and.callFake((arg: moment.Moment) => {
        expect(arg.toISOString()).toEqual(
          scenario.expectedResult.toISOString()
        );
      });
    });
  }));
});
4

3 回答 3

1

当您想在调用时调用假方法时使用callFake 。话虽如此,它应该位于调用该方法之前。

Jasmine 有一个名为toHaveBeenCalledWith()的匹配器,因此您可以验证registerOnChange参数。

  it(`changing control value should return correct date value`, fakeAsync(() => {
    // arrange
    ...
    spyOn(component, 'registerOnChange')

    // act
    fixture.detectChanges();
    fixture.whenStable().then(() => {

      ...

      expect(component.registerOnChange).toHaveBeenCalledWith(scenario.expectedResult.toISOString());
    });
  }));

于 2021-02-16T03:46:12.293 回答
1

您可以利用mostRecent. 茉莉花医生jasmine

spyOn(component, 'registerOnChange');
...
fixture.detectChanges();
...
expect(component.registerOnChange.calls.mostRecent()).toEqual();

编辑:这可能不是最干净的方法,但我们可以将函数调用字符串化,然后在字符串上断言。

const mostRecent = component.registerOnChange.calls.mostRecent();
expect(mostRecent.toString()).toContain(/*...*/);

要对函数进行字符串化,请查看以下代码段。

在此处输入图像描述

于 2021-02-16T13:49:11.563 回答
0

基于AliF50 的回答,我想出了一个目前似乎适用于这种情况的次优解决方案。由于我知道被测组件的内部 API,我可以存储回调函数spyOn的成员(在本例中为)。privateonChange

但是,如果该成员被重命名或重构,这将中断private onChange,因此最好有一个测试来测试它public registerOnChange

...
scenarioArray.forEach((scenario) => {
  it(`changing control value should return correct date value`, fakeAsync(() => {
    // arrange
    spyOn<any>(component, 'onChange'); // Answer: spyOn private member
    component.writeValue(scenario.writtenControlValue);

    // act
    fixture.detectChanges();
    fixture.whenStable().then(() => {
      const input = fixture.debugElement.query(By.css('input')).nativeElement;
      input.value = scenario.newControlValue;
      input.dispatchEvent(new Event('input'));

      // assert
      expect(component['onChange'].calls.mostRecent().args[0].toISOString()).toEqual(
        scenario.expectedResult.toISOString()
      );
    });
  }));
});
于 2021-02-16T16:55:13.203 回答