Javascript 模拟作为参数传递到对象中的回调

Javascript 模拟作为参数传递到对象中的回调,javascript,angular,unit-testing,typescript,karma-jasmine,Javascript,Angular,Unit Testing,Typescript,Karma Jasmine,我尝试测试一个模式服务,但不幸的是,我不知道如何模拟作为参数传递给服务的回调«ok»和«cancel»。我的单元测试通过了,但覆盖需要一些爱: 我的组件类: export class TestComponent { constructor(private _modalService : ModalService) {} public show() : void { this._modalService.showModal(DefaultModalCompone

我尝试测试一个模式服务,但不幸的是,我不知道如何模拟作为参数传递给服务的回调«ok»和«cancel»。我的单元测试通过了,但覆盖需要一些爱:

我的组件类:

export class TestComponent {

    constructor(private _modalService : ModalService) {}

    public show() : void {
        this._modalService.showModal(DefaultModalComponent, {
            ok: () => {
                alert("Ok have been clicked.");
                this._modalService.hide();
            },
            cancel: () => {
                alert("Cancel have been clicked.");
                this._modalService.hide();
            }
        });
    }
}
我的单元测试类如下所示:

describe("TestComponent", () => {

    let _modalService = jasmine.createSpyObj("ModalService", ["show"]);

    beforeEach(() => {
        TestBed.resetTestEnvironment();
        TestBed.initTestEnvironment(BrowserDynamicTestingModule, platformBrowserDynamicTesting());
        TestBed.configureTestingModule({
            imports: [BrowserAnimationsModule],
            schemas: [NO_ERRORS_SCHEMA],
            declarations: [TestComponent],
            providers: [{ provide: ModalService, useValue: _modalService }]
        });
     });

     let _component: any;
     let _element: any;

     beforeEach(done => {
         TestBed.compileComponents().then(() => {
             let fixture: ComponentFixture<TestComponent> = TestBed.createComponent(TestComponent);
             fixture.detectChanges();
             _component = fixture.componentInstance;
             _element = fixture.nativeElement;

             done();
         });
     });

    describe("show()", () => {
        it("should have called show method from service with parameters provided", done => {
            _component.show();

            expect(_modalService.show).toHaveBeenCalled();

            done();
        });
    });
});
description(“TestComponent”),()=>{
让_modalService=jasmine.createSpyObj(“modalService”,“show”);
在每个之前(()=>{
TestBed.resetTestEnvironment();
initTestEnvironment(BrowserDynamicTestingModule,platformBrowserDynamicTesting());
TestBed.configureTestingModule({
导入:[浏览动画模块],
模式:[无错误模式],
声明:[TestComponent],
提供者:[{provide:ModalService,useValue:_ModalService}]
});
});
let_分量:任意;
let_元素:任意;
每次之前(完成=>{
TestBed.compileComponents()。然后(()=>{
let fixture:ComponentFixture=TestBed.createComponent(TestComponent);
fixture.detectChanges();
_组件=fixture.componentInstance;
_元素=fixture.nativeElement;
完成();
});
});
描述(“show()”,()=>{
它(“应该使用提供的参数从服务调用show方法”,done=>{
_component.show();
期望(_modalService.show).tohavebeincalled();
完成();
});
});
});

可以通过测试友好的方式重构服务:

modalOkHandler = () => { ... }

modalCancelHandler = () => { ... }

public show() : void {
    this._modalService.showModal(DefaultModalComponent, {
        ok: this.modalOkHandler,
        cancel: this.modalCancelHandler
    });
}
这样就可以在被调用的方法上断言回调:

_component.show();
expect(_modalService.show).toHaveBeenCalledWith(DefaultModalComponent, {
  ok: modalService.modalOkHandler,
  cancel: modalService.modalCancelHandler
});
另一种选择不那么方便。对于匿名函数,应改为测试方法参数:

_component.show();
expect(_modalService.show).toHaveBeenCalledWith(DefaultModalComponent, {
  ok: jasmine.any(Function),
  cancel: jasmine.any(Function)
});

const [, { ok, cancel }] = _component.show.calls.first().args;
spyOn(window, 'alert');
expect(_modalService.hide).toHaveBeenCalledTimes(0);
ok();
expect(alert).toHaveBeenCalledWith(...);
expect(_modalService.hide).toHaveBeenCalledTimes(1);
...