如何模拟在 Angular 中组件声明中调用的方法?

How do I mock a method that is called in my component's declaration in Angular?

我有一个 Angular 11 组件,它将用户的时区设置为 属性。

export class AppComponent implements OnInit {

  timezone: string =  Intl.DateTimeFormat().resolvedOptions().timeZone;

  // ...
}

这个效果不错,我觉得1。现在我正在尝试为使用此 属性 的代码编写单元测试。在我的规范文件中,我有这段代码。

describe('AppComponent', () => {
  let fixture: ComponentFixture<AppComponent>;
  let component: AppComponent;
  let loader: HarnessLoader;

  beforeEach(
    waitForAsync(() => {
      spyOn(Intl.DateTimeFormat(), 'resolvedOptions').and.returnValue({
        timeZone: 'America/Sao_Paulo', // this is the mocked value
        calendar: 'gregory',           // ... and the rest is just the output from Europe/London
        day: '2-digit',
        locale: 'en-GB',
        month: '2-digit',
        numberingSystem: 'latn',
        year: 'numeric',
      });

      TestBed.configureTestingModule({
        declarations: [AppComponent],
      }).compileComponents();
      fixture = TestBed.createComponent(AppComponent);
      component = fixture.componentInstance;
      loader = TestbedHarnessEnvironment.loader(fixture);
    })
  );

  describe('The User Interface', () => {
    beforeEach(async () => {
      fixture.detectChanges();
      component.ngOnInit();
    });

   it('should render timezone', () => {
      const compiled = fixture.nativeElement;
      expect(
        compiled.querySelector('.tz').textContent
      ).toContain('America/Sao_Paulo');
    });
  });
});

代码可以编译,但测试失败并找到我当地的 "Europe/London" 时区。我怀疑我在错误的时间做模拟。

我想也许我的声明需要保存在稍后执行的某个地方,所以我试图将它移到 constructorngOnInit() 中,但它们都没有改变任何东西。

当我尝试使用 jasmine.clock().install()mockDate() 时,我的测试超时,一切都崩溃了。

我怎样才能让那个模拟工作,以便我的组件得到一个假的时区?


1) 我可能应该更改计算机的时区以检查它是否真的...

您在错误的对象上设置了间谍。 当 运行 Intl.DateTimeFormat() 您在测试和组件中创建一个新对象时。

您可能应该监视 DateTimeFormat。

spyOn<any>(Intl, "DateTimeFormat").and.returnValue({
    resolvedOptions: () => ({timeZone: 'MockTimezone'})
})