Jasmine createSpyObj服务未注册呼叫

时间:2018-06-22 13:39:16

标签: angular service jasmine

在阅读了关于茉莉花间谍未注册呼叫的每条帖子的感觉后,这是我的代码中的确切问题:

describe( 'shared.FormAutocompleteComponent', () => {
    let component: FormAutocompleteComponent;
    let fixture: ComponentFixture<FormAutocompleteComponent>;
    let displayCtrl: FormControl;

    const mockService = jasmine.createSpyObj( 'dynSearchService', ['search', 'lookup'] );
    mockService.lookup.and.returnValue( of( { unlocode: 'ZRH/CH', name: 'Zürich' } ) );
    mockService.search.and.returnValue( of( [{ unlocode: 'ZRH/CH', name: 'Zürich' }] ) );

    beforeEach( async(() => {
        TestBed.configureTestingModule( {
            declarations: [FormAutocompleteComponent],
            providers: [{ provide: DynamicSearchService, useValue: mockService }],
            imports: [
                NoopAnimationsModule, ReactiveFormsModule,
                RouterTestingModule.withRoutes( [] ),
                MatInputModule, MatAutocompleteModule, MatIconModule
            ]
        } )
            .compileComponents();
    } ) );

    beforeEach(() => {
        displayCtrl = new FormControl();
        const group = new FormGroup( {} );
        group.addControl( 'foobar', displayCtrl );

        fixture = TestBed.createComponent( FormAutocompleteComponent );
        component = fixture.componentInstance;
        component.config = {
            name: 'foobar',
            formControl: 'text',
            label: 'My foobar',
            lookupApi: 'location',
            searchApi: 'locations'
        };
        component.group = group;
        fixture.detectChanges();
    } );

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

    fit( 'should correctly extend single term to wildcard', async(() => {
        // arrange
        displayCtrl.setValue( 'zrh' );
        fixture.detectChanges();
        // act
        component.search();
        // assert
        expect( mockService.search ).toHaveBeenCalled();
        expect( mockService.search ).toHaveBeenCalledWith( 'zrh*', 'locations' );
    } ) );
} );

将DynamicSearchService注入FormAutocompleteComponent,并在组件调用DynamicSearchService#search之前直接放置一个console.log,以表明该方法已被明确调用。另一个console.log显示返回的结果与火车Jasmine spy的结果相匹配。

3396 (Windows 10 0.0.0)]: Connected on socket rlx5hC9uWlNSUz0pAAAA with id 73910165
LOG: 'callDynSearchService with displayCtrl.value=zrh'
LOG: 'callDynSearchService with displayCtrl.value=zrh'
LOG: 'About to run <search> on service with term zr* '
LOG: 'About to run <search> on service with term zr* '
LOG: 'Got results: [{"unlocode":"ZRH/CH","name":"Zürich"}]'
LOG: 'Got results: [{"unlocode":"ZRH/CH","name":"Zürich"}]'
Chrome 67.0.3396 (Windows 10 0.0.0) shared.FormAutocompleteComponent should correctly extend single term to wildcard FAILED
        Expected spy dynSearchService.search to have been called.
            at <Jasmine>

运行测试

const srv = fixture.debugElement.injector.get( DynamicSearchService );
expect( mockService ).toEqual( srv );

成功,唯一留下的原因似乎是.search()调用从未记录在间谍程序上。我在做什么错了?

编辑,2018年6月23日

更改为定义非间谍的模拟服务(仍注入了“ useValue”),然后

fit( 'should correctly extend single term to wildcard', async(() => {
    // arrange
    let injectedService = TestBed.get( DynamicSearchService );
    spyOn( injectedService, 'search' ).and.callThrough();
    spyOn( injectedService, 'lookup' ).and.callThrough();
    displayCtrl.setValue( 'zrh' );
    fixture.detectChanges();
    // act
    component.search();
    // assert
    expect( injectedService.search ).toHaveBeenCalled();
} ) );

调试现在显示组件中的服务与“ injectedService”是同一对象。 spyOn完成的代理更改也会显示在组件服务上。但是,茉莉花仍然记录“搜索”从未被调用过。

1 个答案:

答案 0 :(得分:1)

我猜测原因是对Observable的debounceTime()调用,一些console.log语句显示尽管有async()和Fixture.whenStable(),但搜索仅在之后执行期望()断言运行了。

该问题最终通过切换到fakeAsync并使用tick()得以解决。