如何测试异步函数中设置的变量?

How to test a variable setted in an async function?

我试图在执行异步函数后测试变量的值,但是当我尝试读取它时它是一个空数组(变量应该有一个包含对象的数组),我也把一些 console.log() 在函数内部,它工作正常。

这是我第一次使用 Jasmine 和 Karma,所以任何帮助都很好。

我组件里面的函数

async refresh() {
let requestUserProfile;
let data
// this._fuseSplashScreenService.hide();

// this.showLoading('Cargando documentos...');

//requestUserProfile = this.getUserProfile();
this._restService.getDocumentsLimit(100, 1, undefined).subscribe((documents: any) => {
    //Here is just a part of this function
    this.moreData = documents.data;
});

}

变量 moreData 是我一直试图测试的变量。

测试代码;

describe('DashboardComponent', () => {
  let component: DashboardComponent;
  let fixture: ComponentFixture<DashboardComponent>;

  beforeEach(async () => {
    await TestBed.configureTestingModule({
      imports: [HomeModule, HttpClientModule, RouterTestingModule, NoopAnimationsModule, MatDialogModule ],
      declarations: [ DashboardComponent ]
    })
    .compileComponents();
  });

  beforeEach(() => {
    fixture = TestBed.createComponent(DashboardComponent);
    component = fixture.componentInstance;
    fixture.detectChanges();
  });

  it('should create', () => {
    expect(component).toBeTruthy();
  });

  //This is the one 
  it('should have info', async () =>{
      await component.refresh();
      console.log(component.moreData);
      //expect(component.moreData).not.toBe(null)
  })
});

问题不在于异步函数之类的。在你的测试脚本中,你需要做的是模拟服务,return一些值,然后它会自动覆盖那个变量。

这是您需要做的:

////////////////// Use Injectable and create a mock-service;

@Injectable()
class MockService extends RestService {
  ////////////////////// Mock your method here
  getDocumentsLimit() {
    return of({ 
        data: {
             // You know what response comes here, so use that here;
             someData: 'someDataValue'
        }
    }
  }
}

describe('DashboardComponent', () => {
  let component: DashboardComponent;
  let fixture: ComponentFixture<DashboardComponent>;

  beforeEach(async () => {
    await TestBed.configureTestingModule({
      imports: [HomeModule, HttpClientModule, RouterTestingModule, NoopAnimationsModule, MatDialogModule ],
      declarations: [ DashboardComponent ],
      ///////////////// ADD THIS LINE IN THE PROVIDERS /////////////
      providers: [
          {
            provide: RestService,
            useClass: MockService
          }
      ] 
    })
    .compileComponents();
  });

  beforeEach(() => {
    fixture = TestBed.createComponent(DashboardComponent);
    component = fixture.componentInstance;
    fixture.detectChanges();
  });

  it('should create', () => {
    expect(component).toBeTruthy();
  });

  //This is the one 
  ////////////////////// YOUR TEST CASE WILL BECOME THIS
  it('should have info', () =>{
      spyOn(component, 'refresh').and.callThrough();
      component.refresh();
      expect(component.refresh).toHaveBeenCalled();
  })
});

_restService.getDocumentsLimit(...) 可能 returns 一个异步可观察对象(我假设是 http 调用),这意味着 refresh() returns 立即并且订阅的回调方法是预期的将来有时会被调用(当结果从 http 调用到达时)。但是,测试执行在回调有机会被调用之前终止,因此分配给 this.moreData 永远不会发生。

不希望出现您对测试失去控制的情况。解决方案是摆脱可能会干扰您测试的依赖项,或者更好地说让它们由 mocking.

控制

因此,在您的测试中,您应该模拟 getDocumentsLimit(...) 方法,但这里的关键是让它 return 成为一个带有假数据的同步可观察对象,然后期望 this.moreData 保持那个假数据。