Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
1.3k views
in Technique[技术] by (71.8m points)

unit testing - Angular Jasmine Test: SPEC HAS NO EXPECTATIONS when using setTimeout

I'm trying to write a unit test for a components in my App. It's a very simple component called TroubleShootingPage that is only supposed to show a help page, if someone has trouble somewhere in the rest of my app.

All tests are passing, but in the output in Karma I see a hint: SPEC HAS NO EXPECTATIONS:

My Karma Output

The test that supposedly has no expectations is dealing with the function getTroubleShootingPage() in my TroubleShootingPage Component, which looks like this:

export interface Entry<T> {
    sys: Sys;
    fields: T;
    toPlainObject(): object;
    update(): Promise<Entry<T>>;
}

troubleShootingPage: Entry<any>;

constructor(private contentfulService: ContentfulService) {}

ngOnInit() {
    this.getTroubleShootingPage("en-US")
}

getTroubleShootingPage(locale: string) {
    this.contentfulService.getTroubleShootingPage(locale).then(page => {
      this.troubleShootingPage = page;
      ...
  }
}

As you can see, the content/text of the troubleshooting page has to be loaded from the contentfulService and there it is loaded from an API (Contentful) depending on the user's language. So I only want to secure that the function gets called and that the returned input from the contentfulService gets correctly assigned to the variable this.troubleShootingPage.

The test looks like this:

describe('TroubleshootingPageComponent', () => {
    let component: TroubleshootingPageComponent;
    let fixture: ComponentFixture<TroubleshootingPageComponent>;
    
    let contentfulServiceStub: Partial<ContentfulService> = {
        getTroubleShootingPage: () => {
            return new Promise<Entry<any>>(() => {
                return troubleShootingPageMock;
            });
        }
    };

    let troubleShootingPageMock: Entry<any>;
    troubleShootingPageMock = {
        fields: {
            description: "Please read here for further help:",
            mainText: {},
            textCancelButton: "Quit",
            textConfirmButton: "Continue",
            title: "Need Help?"
        },
        toPlainObject() {
            return null;
        },
        update() {
            return null;
        },
        sys: {
            type: "",
            id: "string",
            createdAt: "string",
            updatedAt: "string",
            locale: "string",
            contentType: {
                sys: null
            },
        },
    };

    beforeEach(async(() => {
        TestBed.configureTestingModule({
            imports: [],
            declarations: [TroubleshootingPageComponent],
            schemas: [NO_ERRORS_SCHEMA],
            providers: [{ provide: ContentfulService, useValue: contentfulServiceStub }]
        })
            .compileComponents();
    }));

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

   it('should get the troubleShootingPage form Contentful', () => {
        component.getTroubleShootingPage("en-GB");
        setTimeout(() => {
            expect(component.troubleShootingPage).toEqual(troubleShootingPageMock.fields);
        }, 1000)
    });

    // I also tried:
    // it('should get the troubleShootingPage form Contentful', (done) => {
    //     component.getTroubleShootingPage("en-GB");
    //     setTimeout(() => {
    //         expect(component.troubleShootingPage).toEqual(troubleShootingPageMock.fields);
    //         done();
    //     }, 1000)
    // });
});

I added a timeout with setTimeout() because without it component.troubleShootingPage was always undefined, because the test went to the ecpect() statement, before the Promise in the getTroubleShootingPage() function was resolved:

it('should get the troubleShootingPage form Contentful', () => {
            component.getTroubleShootingPage("en-GB");
            expect(component.troubleShootingPage).toEqual(troubleShootingPageMock.fields);            
});

-> this fails, because component.troubleShootingPage is undefined.

How could I solve this, any ideas?

question from:https://stackoverflow.com/questions/65875200/angular-jasmine-test-spec-has-no-expectations-when-using-settimeout

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Ok thanks for the comments, the hint with making the function return the promise was the necessary part:

in the component I made one function for only returning the promise:

 getTroubleShootingPage(locale: string) {
    this.getTroubleShootingPageFromService(locale).then(page => {
      this.troubleShootingPage = page;
   })
}

getTroubleShootingPageFromService(locale: string) {
    return this.contentfulService.getTroubleShootingPage(locale);
}

And in my test I have now this, which works fine:

it('should get the troubleShootingPage form Contentful', async () => {
        spyOn(contentfulServiceStub, 'getTroubleShootingPage').and.returnValue(Promise.resolve(troubleShootingPageMock))
        await component.getTroubleShootingPage("en-US");
        expect(component.troubleShootingPage).toEqual(troubleShootingPageMock);
    });

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...