Reputation: 10360
I have a function like this (the code is simplified to make this code more readable)
import Adapter from "adapter-package";
const adapter = new Adapter();
async powerOn(): Promise<MyClass> {
const myClass = new MyClass();
await adapter.powerOn();
return myClass;
}
as you can see I am using await
on the call of adapter.powerOn()
. Now I am writing unit tests for this using Jest.
it("can power on the adapter", async () => {
const spy = jest.spyOn(Adapter.prototype, "powerOn");
const myClass = await MyClass.powerOn();
expect(myClass).toBeInstanceOf(MyClass);
expect(spy).toHaveBeenAwaitedFor();
^^^^^^^^^^^^^^^^^^^^
spy.mockRestore();
}, 10000);
The test that I have underlined does not exist, but it is what I would like to test. Can I know if a method I have called has been waited for?
edit:
Will Jenkins pointed out that it is not clear what I am asking. Basically I want to make sure that the Promise returned by adapter.powerOn()
has been resolved by the time my function has been resolved. Because I already had an issue where I accidentially had removed the await
before adapter.powerOn()
.
async powerOn(): Promise { const myClass = new MyClass(); adapter.powerOn(); return myClass; }
So when I called my function with
await powerOn();
that function was resolved, but it did not await the call to adapter.powerOn()
and I had to spend some time debugging. So I would like to make sure that adapter.powerOn()
is resolved by the time await powerOn()
completes.
Upvotes: 1
Views: 838
Reputation: 10360
This is the solution I found:
import { inspect } from "util";
it("waits for the adapter to have been powered on", async () => {
const spy = jest
.spyOn(Adapter.prototype, "powerOn")
.mockImplementation(() => new Promise<void>(res => setTimeout(res, 0)));
await Sblendid.powerOn();
const spyPromise = spy.mock.results[0].value;
expect(inspect(spyPromise)).toBe("Promise { undefined }");
}, 10000);
the line
spy.mock.results[0].value
will get me the promise returned by my mock. Using util.inspect
on a promise
expect(inspect(spyPromise)).toBe("Promise { undefined }");
will give me "Promise { undefined }"
on a fulfilled promise (that is returning undefined
) and would return "Promise { <pending> }"
if it weren't fulfilled, that is how I test it has been resolved (fulfilled) when await Sblendid.powerOn();
completed.
Upvotes: 0
Reputation: 9787
How about something like this?
it("can power on the adapter", async () => {
let hasResolved = false;
const spy = jest.spyOn(Adapter.prototype, "powerOn");
const myClass = await MyClass.powerOn();
expect(myClass).toBeInstanceOf(MyClass);
let hasResolved = false;
//if it has been awaited then this should complete
spy.returnValues[0].then(()=>{
hasResolved=true;
})
expect(hasResolved).to.be.true;
spy.mockRestore();
}, 10000)
Upvotes: 1
Reputation: 1447
You could use setInmediate
to wait for all pending promises:
const flushPromises = () => new Promise(setImmediate);
it("can power on the adapter", async () => {
const spy = jest.spyOn(Adapter.prototype, "powerOn");
await expect(MyClass.powerOn()).resolves.toBeInstanceOf(MyClass);
await expect(flushPromises()).resolves.toBeTruthy();
}, 10000);
This test first checks if powerOn
resolves and returns an instance of MyClass
and then checks if every pending promise has been resolved or rejected.
Upvotes: 0