验证rxjs订阅内部的方法调用

问题描述 投票:0回答:1

我有一个角度应用程序,正在尝试为其创建单元测试。有一种特殊的方法,它通过可观察的管道和承诺的复杂链来创建一个可观察的对象,然后订阅所创建的可观察对象。我需要验证在订阅内部进行的方法调用。

结构是这样的:

private obs$: Observable<T>;
private subscription: Subscription;

methodToTest(): void {
  this.obs$ = from( ... ).then( /* chain of piped observables */ );
  this.subscription = this.obs$
    .subscribe(
        (value: T) => {
          // bunch of logic
          methodToBeVerifiedWasCalled();
        },
        (error) => { /* error handling */ }
    );
}

到目前为止,我的测试看起来像这样:

it('the method to be verified is successfully called', () => {
  // various mocking set up
  this.mockApi.methodThatReturnsAPromise.and.returnvalue(Promise.resolve());
  // etc.

  this.classUnderTest.methodToTest();

  // assertions for the various mocks...
  expect(this.mockApi.methodThatReturnsAPromise).toHaveBeenCalled();
  // etc.

  // assert that the target method was called:
  expect(this.classUnderTest.methodToBeVerifiedWasCalled).toHaveBeenCalled();
  expect(this.classUnderTest.subscription).toBeDefined();
});

当然,该测试在最后的断言中失败,因为methodToBeVerifiedWasCalled实际上是在订阅块内部调用的,并且该测试只是在同步地运行。 (在这里,classUnderTest是一个间谍对象,其中methodToBeVerifiedWasCalled被监视。)

由于该方法为可观察对象分配了一个值,所以我不能仅在异步测试中订阅classUndertest.obs$并验证返回的值(无论如何,这实际上并不能帮助解决问题。)我如何验证订阅块内部的方法被调用?

我不能更改源代码,只能更改测试。

javascript rxjs jasmine karma-runner
1个回答
1
投票

您需要使测试异步,然后在methodToTest()之后等待。如果methodToTest()没有返回您可以等待的承诺或可观察的结果,那么您将被迫等待一段时间。类似于:

function delay(ms) {
  return new Promise(resolve => setTimeout(ms, resolve));
}

it('the method to be verified is successfully called', async (done) => {
  // various mocking set up
  this.mockApi.methodThatReturnsAPromise.and.returnvalue(Promise.resolve());
  // etc.

  const result = this.classUnderTest.methodToTest();
  // if the method actually returned a promise you could: await result;
  // since it does not, you can just await time:
  await delay(1000); // wait 1 second

  // assertions for the various mocks...
  expect(this.mockApi.methodThatReturnsAPromise).toHaveBeenCalled();
  // etc.

  // assert that the target method was called:
  expect(this.classUnderTest.methodToBeVerifiedWasCalled).toHaveBeenCalled();
  expect(this.classUnderTest.subscription).toBeDefined();

  // tell jasmine test is done
  done();
});
© www.soinside.com 2019 - 2024. All rights reserved.