Angular jasmine中组件异步/等待函数的角度单元测试

Angular jasmine中组件异步/等待函数的角度单元测试,angular,typescript,unit-testing,jasmine,Angular,Typescript,Unit Testing,Jasmine,我想测试服务返回的对象是否调用特定的方法 组件方法是async,因为服务将返回Promise 这是组件代码 // component export class FilterComponent { constructor( private modalController: ModalController, ) { } async onFilterClicked() { const modal = await this.modalController.create({

我想测试服务返回的对象是否调用特定的方法

组件方法是
async
,因为服务将返回
Promise

这是组件代码

// component
export class FilterComponent {
  constructor(
    private modalController: ModalController,
  ) { }

  async onFilterClicked() {
    const modal = await this.modalController.create({
      component: FilterModalPage,
    });

    modal.onDidDismiss().then(res => {
      if (res.data) {
        // do something
      }
    });

    await modal.present();
  }
}
这是我的测试

describe('FilterComponent', () => {
  let fixture: ComponentFixture<FilterComponent>;
  let component: FilterComponent;
  let modalControllerSpy;
  let modalSpy;

  beforeEach(async () => {
    modalControllerSpy = jasmine.createSpyObj('modalController', ['create']);
    modalSpy = jasmine.createSpyObj('modal', ['present']);

    TestBed.configureTestingModule({
      declarations: [FilterComponent],
      providers: [
        { provide: ModalController, useValue: modalControllerSpy },
      ]
    }).compileComponents();
  });

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

  describe('onFilterClicked', () => {
    it('should `present` the modal', () => {
      modalControllerSpy.create.and.returnValue(modalSpy);

      component.onFilterClicked();
      fixture.detectChanges();

      expect(modalControllerSpy.create).toHaveBeenCalled(); // success
      expect(modalSpy.present).toHaveBeenCalled(); // fail :( how to test `present` is called????
    });
  });
});
我想测试我的
modalSpy
是否调用
present
函数。
也许我在这里做错了。

来自
create()
的返回值需要是一个承诺。请尝试以下操作:

it('should `present` the modal', () => {
  modalControllerSpy.create.and.returnValue(Promise.resolve(modalSpy));

  component.onFilterClicked();
  fixture.detectChanges();

  expect(modalControllerSpy.create).toHaveBeenCalled(); // success
  expect(modalSpy.present).toHaveBeenCalled(); // should pass now
});

参见文档

我将重构测试套件,如下所示:

// ...
// create a valid response for ModalController#create according to the logic in controller where it is used
const modalObj = {
  onDidDismiss: () => Promise.resolve({ res: { data: 'test-value1' } })
};

// ...
beforeEach(async () => {
  // create a spy object with the methods you want to spy on
  modalControllerSpy = jasmine.createSpyObj('ModalController', ['create', 'present']);

  // mock the returned value from the service
  modalControllerSpy.create.and.returnValue(modalObj);
  modalControllerSpy.present.and.returnValue(Promise.resolve('test-value2'));

  TestBed.configureTestingModule({
    declarations: [FilterComponent],
    providers: [
      { provide: ModalController, useValue: modalControllerSpy },
    ]
  }).compileComponents();
});
// ... 
  it('should `present` the modal', () => {
    component.onFilterClicked();
    fixture.detectChanges();   // maybe you don't need this, check if the test passes without it

    expect(modalControllerSpy.create).toHaveBeenCalled();
    expect(modalControllerSpy.present).toHaveBeenCalled();
    // you could add some additional checks here regarding to the returned values
    // in the promises since they were mocked: 'test-value1' and 'test-value2'
  });
});
// ...

你查过答案了吗?如有任何反馈,将不胜感激。
// ...
// create a valid response for ModalController#create according to the logic in controller where it is used
const modalObj = {
  onDidDismiss: () => Promise.resolve({ res: { data: 'test-value1' } })
};

// ...
beforeEach(async () => {
  // create a spy object with the methods you want to spy on
  modalControllerSpy = jasmine.createSpyObj('ModalController', ['create', 'present']);

  // mock the returned value from the service
  modalControllerSpy.create.and.returnValue(modalObj);
  modalControllerSpy.present.and.returnValue(Promise.resolve('test-value2'));

  TestBed.configureTestingModule({
    declarations: [FilterComponent],
    providers: [
      { provide: ModalController, useValue: modalControllerSpy },
    ]
  }).compileComponents();
});
// ... 
  it('should `present` the modal', () => {
    component.onFilterClicked();
    fixture.detectChanges();   // maybe you don't need this, check if the test passes without it

    expect(modalControllerSpy.create).toHaveBeenCalled();
    expect(modalControllerSpy.present).toHaveBeenCalled();
    // you could add some additional checks here regarding to the returned values
    // in the promises since they were mocked: 'test-value1' and 'test-value2'
  });
});
// ...