【问题标题】:Testing function inside of subscribe订阅内部的测试功能
【发布时间】:2021-11-10 22:00:44
【问题描述】:

在函数内部(在这种情况下为ngOnInit),我订阅了一个可观察对象。当我获得新数据时,我会使用该数据更新另一个函数:

 
ngOnInit(): void {
    this.observable$.subscribe({
      next: (data) => {
        this.function(data)
      },
    });
  }
 
function(data): void {
  console.log(data)
}

当我需要对此进行测试时,问题就来了。我已经尝试了我能找到的所有在线答案的方法,例如In Jest, how can I unit test a method that subscribes to an observable(我没有我在嘲笑的服务)和Angular - Function inside subscribe never called in unit test(不是开玩笑),以下是我目前的尝试:

 let component: MyComponent;
  let fixture: ComponentFixture<MyComponent>;
 
  beforeEach(async () => {
    await TestBed.configureTestingModule({
      imports: [Modules],
      providers: [provideMock({})],
    }).compileComponents();
  });
 
  beforeEach(() => {
    fixture = TestBed.createComponent(MyComponent);
    component = fixture.componentInstance;
    component['observable$'] = { subscribe: jest.fn() } as unknown as Observable<Type>;
    fixture.detectChanges();
  });
 
describe('ngOnInit', () => {
    it('should call function with Data', (done) => {
      const holdingsAndCashAccounts = [mockHolding(), mockCashAccount()];
      jest.spyOn(component, 'function')
 
      component['observable$'] = of(observableContent);
 
      component['observable$'].subscribe({
        next: (data) => {
          expect(component.function).toHaveBeenCalledWith(data);
          done();
        },
      });
    });
  });

但我从这个得到 numberOfCalls: 0。

【问题讨论】:

  • 你为什么要订阅测试中的 observable,或者监视你应该测试的东西?为什么 test double 不是一个真正的 observable,而不仅仅是一个具有 subscribe 属性的对象?测试行为:给定一个发出值的可观察对象,该值是否被记录?
  • @jonrsharpe 感谢您的回复。我已经在这几个小时了,这只是我最近的尝试——但我想要测试的是,函数是用数据调用的。我不太确定你在建议我做什么,你有没有机会为我改写一下或举个例子?

标签: angular rxjs jestjs


【解决方案1】:

您可以在测试中使用一个主题以获得更好的控制,并为有问题的可观察对象提供 .asObservable。然后,您可以使用测试中想要的任何值调用 .next。

所以在你的 fixture.detectChanges() 之前的 beforeEach 中是这样的

testSubject = new Subject<any>();
component.observable$ = testSubject.asObservable();
fixture.detectChanges();

然后在你的测试中像这样

  spyOn(component, 'function'); //This is for Jasmine, jest.spyOn should work as well
  expect(component.function).toHaveBeenCalledTimes(0);
  const testData = { prop1: 1, prop2: '2' };
  testSubject.next(testData);
  expect(component.function).toHaveBeenCalledTimes(1);
  expect(component.function).toHaveBeenCalledWith(testData);

这是一个使用 Jasmine 的 stackblitz 示例(因为我找不到使用 Jest 进行分叉的类似项目)。在这里你可以看到我只是将它作为组件的公共字段提供。

https://stackblitz.com/edit/jasmine-in-angular-xdsfqk?file=src%2Fapp%2Fapp.component.spec.ts

看起来你的 observable 可能是私有的,在这种情况下,我建议不管它是如何创建的都进行模拟。

如前所述,测试行为很好,如果可以,您可以将函数设为私有。但我确实认为监视您希望在同一个类中调用的公共函数是有价值的,进而对这些函数进行更精细的测试。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-03-09
    • 2018-11-23
    • 2018-02-01
    • 1970-01-01
    • 2019-11-24
    • 1970-01-01
    相关资源
    最近更新 更多