我有promise 功能waitUntilIsReady:

  (...)

  private inProgressSubject = new BehaviorSubject<boolean>(true)

  waitUntilIsReady(): Promise<void> {
    const untilInProgress = new Subject<void>()

    return new Promise((resolve) => {
      this.inProgress.pipe(takeUntil(untilInProgress)).subscribe((inProgress) => {
        if (inProgress) {
          return
        }

        untilInProgress.next()
        untilInProgress.complete()
        resolve()
      })
    })
  }

  (...)

我使用它来确保只有在一切准备就绪时才运行一些特定的代码(在init上).

  ngOnInit(): void {
    this.service.waitUntilUserIsReady().then(() => {
      this.otherService.doSomething()
    })
  }

第一个问题是:如何编写测试来判断呼叫doSomething()是否只在promise 解决之后运行,而不是在此之前运行?

从上面的问题中产生了一个主要的问题:How to create Promise without resolving it to be resolved after some time in test?

这类似于在测试中创建Observable Subject并调用next,如下所示:

const fakeSubject = new Subject<Message>()

describe('Xyz', () => {
  let spectator: Spectator<Xyz>
  const createComponent = createComponentFactory({
    component: Xyz,
    providers: [
      MockProvider(Service, {
        someObservableToChangeFlag: fakeSubject.asObservable()
      }),
      MockProvider(OtherService, {
        doSomething: jasmine.createSpy()
      }),
    ],
  })

  beforeEach(() => (spectator = createComponent()))

  it('should something', fakeAsync(() => {
    const otherService = spectator.inject(OtherService)

    expect(otherService.doSomething).not.toHaveBeenCalled()

    someObservableToChangeFlag.next()
    tick()

    expect(otherService.doSomething).toHaveBeenCalled()
  }))

我只知道如何测试它是否运行,而不判断是否在Promise函数中:

escribe('Xyz', () => {
  let spectator: Spectator<Xyz>
  const createComponent = createComponentFactory({
    component: Xyz,
    providers: [
      MockProvider(Service, {
        waitUntilIsReady: jasmine.createSpy().and.resolveTo(),
      }),
      MockProvider(OtherService, {
        doSomething: jasmine.createSpy()
      }),
    ],
  })

  beforeEach(fakeAsync(() => (spectator = createComponent())))

  it('should "Do something" on promise', () => { // <- This test is not preventing from simply moving logic out side of Promise
    const otherService = spectator.inject(OtherService)

    expect(otherService.doSomething).toHaveBeenCalled()
  })

  it('should "Do something" on promise', fakeAsync(() => { // <- Something "like" what I want
    const otherService = spectator.inject(OtherService)

    // Assert if nothing happened
    expect(otherService.doSomething).not.toHaveBeenCalled()
    
    // Trigger Promise
    ? promise.trigger() ?
    tick()

    // Assert if logic inside of Promise was called
    expect(otherService.doSomething).toHaveBeenCalled()
  }))

我试过了

waitUntilIsReady: jasmine.createSpy().and.returnValue(Observable.of().pipe(delay(500)).toPromise()),

toPromise是不受欢迎的.

推荐答案

beforeEach函数中,您可以创建一个Promise,并将其resolve函数赋给一个可以在单元测试中调用/触发的变量.

describe('Xyz', () => {
  let promise;
  let resolve;  
  let spectator: Spectator<Xyz>;
  const createComponent = createComponentFactory({
    component: Xyz,
    providers: [
      MockProvider(Service, {
        waitUntilIsReady: jasmine.createSpy().and.returnValue(promise),
      }),
      MockProvider(OtherService, {
        doSomething: jasmine.createSpy()
      }),
    ],
  });

  beforeEach(() => {
    promise = new Promise((res) => resolve = res);
    spectator = createComponent();
  });

  it('should "Do something" on promise', fakeAsync(() => { 
    // given
    const otherService = spectator.inject(OtherService);
    expect(otherService.doSomething).not.toHaveBeenCalled();
    
    // when
    resolve();
    tick();

    // then
    expect(otherService.doSomething).toHaveBeenCalled();
  }));
  
});

Typescript相关问答推荐

Angular 17 -如何在for循环内创建一些加载?

更新:Typescript实用程序函数合并对象键路径

如何在TypeScript对象迭代中根据键推断值类型?

如何使用泛型自动推断TS中的类型

TypeScrip 5.3和5.4-对`Readonly<;[...number[],字符串]>;`的测试版处理:有什么变化?

如何将所有props传递给React中的组件?

如何使用Geojson模块和@Types/Geojson类型解析TypeScrip中的GeoJSON?

类型TTextKey不能用于索引类型 ;TOption

如果数组使用Reaction-Hook-Form更改,则重新呈现表单

在VSCode中显示eslint错误,但在终端中运行eslint命令时不显示?(Vite,React,TypeScript)

如何从输入中删除值0

如何在省略一个参数的情况下从函数类型中提取参数类型?

使用泛型识别对象值类型

为什么&Quot;元素隐式具有';Any';类型,因为...即使我已经打字了,也不能作为索引显示错误吗?

扩展对象的此内容(&Q;)

顶点堆叠的图表条形图未在正确的x轴上显示

使用强制转换编写打字函数的惯用方法

有没有什么方法可以使用ProvideState()提供多个削减器作为根减减器

如何使用 AWS CDK 扩展默认 ALB 控制器策略?

Next 13 + React 18 createContext 类型的构建问题