简体   繁体   中英

How do I resolve Promise in mocked function?

I'm trying to test method which returns Promise and resolves in another method which I want to mock. I can test it without mocking but I don't want to because of credentials which wouldn't work on another machine.

Here's my Service code ( PollyService.ts ):

@Service()
export class PollyService {
    @Inject()
    private polly: Polly; // aws-sdk Polly
    url: string;

    getSpeech(body: any) {
        return new Promise((resolve) => {
            let voice: string = (voices as any)[body.code];

            let params = {
               exampleParam: example
            };

            this.polly.synthesizeSpeech(params, (error: any, data: any) => {
                if (error) throw error;
                else {
                    resolve(data);
                }
            });
        });
    }
}

Here's test ( app.spec.ts )

describe('PollyService', () => {
    afterEach(() => {
        Container.reset();
    });
    it ('Should return data', async () => {
        const event: any = {
            body: {
                sentence: "potato",
                code: "en"
            }
        };
        let polly = Container.get(Polly); // aws-sdk polly 
        spyOn(polly, 'synthesizeSpeech'); // and here I want to resolve Promise

        await Container.get(PollyService).getSpeech(event.body);
    });
});

When I am mocking that without resolving promise there is error:

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

How can i simulate resolving Promise in tests?

If you want to create a promise which is already resolved, you can simply use Promise.resolve(someData)

In your case it should be something like this:

spyOn(polly, 'synthesizeSpeech').and.returnValue(Promise.resolve('mockedData'));

Note: You get the timeout error message because you are neither returning the promise in the end of your function nor make use of the done callback.

either do:

    ...
    return await Container.get(PollyService).getSpeech(event.body);

or

describe('PollyService', () => {
    afterEach(() => {
        Container.reset();
    });
    it ('Should return data', async (done) => { // <- done is the callback
        const event: any = {
            body: {
                sentence: "potato",
                code: "en"
            }
        };
        let polly = Container.get(Polly);
        spyOn(polly, 'synthesizeSpeech');

        await Container.get(PollyService).getSpeech(event.body);
        done(); // <- calling it will tell jasmine your test is over
    });
});

Usually either you choose to return the promise or use the callback. I am not sure on how jasmine mix async methods and the callback in the same method but it should work. More information here

You should extend the spyOn with and.returnValue as follows:

const data = ... // define the data to be returned by synthesizeSpeech
spyOn(polly, 'synthesizeSpeech').and.returnValue(Promise.resolve(data));

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM