0

I would like to ask what is the common practice of testing properties which receives data from services inline.

I am not able to test my property which is being receiving values from service - defined inline. here is my property

    readonly filters$ = forkJoin({
        institutions: this.dataExtractService.getInstitutions(),
        dataSetTypes: this.dataExtractService.getDataSetTypes()
    });

getInstitutions() and getDataSetTypes() return Observable<string()>

Here is my spec

    let component: ExtractRetrievalComponent;
    let fixture: ComponentFixture<ExtractRetrievalComponent>;
    let formBuilder: FormBuilder;
    let dataExtractService: DataExtractService;

    beforeEach(() => {
        TestBed.configureTestingModule({
            schemas: [NO_ERRORS_SCHEMA],
            imports: [HttpClientTestingModule],
            declarations: [ExtractRetrievalComponent],
            providers: [
                FormBuilder, DataExtractService
            ]
        }).compileComponents();
        fixture = TestBed.createComponent(ExtractRetrievalComponent);
        component = fixture.componentInstance;

        formBuilder = TestBed.inject(FormBuilder);
        dataExtractService = TestBed.inject(DataExtractService);
        fixture.detectChanges();
    });

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

    it('should get filters', (done) => {
        const expectedInstitution = ['expectedInstitutions'] as string[];
        const expectedDataSetType = ['expectedDataSetType'] as string[];
        const expectedFilter = {
            institutions: expectedInstitution,
            dataSetTypes: expectedDataSetType
        };
        spyOn(component.filters$, 'subscribe').and.callThrough();

        spyOn(dataExtractService, 'getInstitutions').and.returnValue(of(expectedInstitution));
        spyOn(dataExtractService, 'getDataSetTypes').and.returnValue(of(expectedDataSetType));
        fixture.detectChanges();

        component.filters$.subscribe(result => {
            expect(result).toEqual(expectedFilter);
            done();
        });
    });

test is failing with result

Error: Timeout - Async function did not complete within 5000ms (set by jasmine.DEFAULT_TIMEOUT_INTERVAL)

I have also incerased the timeout interval with no luck. Any hints?

PhobossFO
  • 17
  • 3

1 Answers1

0

Since the filters$ is an instance variable, the following lines are happening too late:

spyOn(dataExtractService, 'getInstitutions').and.returnValue(of(expectedInstitution));
spyOn(dataExtractService, 'getDataSetTypes').and.returnValue(of(expectedDataSetType));

The first fixture.detectChanges() calls ngOnInit and I think createComponent creates the class and populates the instance variables. For a quick fix, try this:

dataExtractService = TestBed.inject(DataExtractService); // get a handle on dataExtractService
// spy on their methods
spyOn(dataExtractService, 'getInstitutions').and.returnValue(of(expectedInstitution));
spyOn(dataExtractService, 'getDataSetTypes').and.returnValue(of(expectedDataSetType));
// create the component
fixture = TestBed.createComponent(ExtractRetrievalComponent);
component = fixture.componentInstance;

formBuilder = TestBed.inject(FormBuilder);
fixture.detectChanges();
it('should get filters', (done) => {
        const expectedInstitution = ['expectedInstitutions'] as string[];
        const expectedDataSetType = ['expectedDataSetType'] as string[];
        const expectedFilter = {
            institutions: expectedInstitution,
            dataSetTypes: expectedDataSetType
        };
        spyOn(component.filters$, 'subscribe').and.callThrough();

        component.filters$.subscribe(result => {
            expect(result).toEqual(expectedFilter);
            done();
        });
    });
AliF50
  • 16,947
  • 1
  • 21
  • 37