(This seems partially overlapping with my previous question: Test interaction with two interval async functions)
Using jest 27.5.1 and sinon 13.0.1, I want to unit-test an async interval function.
Consider this code:
const fs = require("fs")
const { exec } = require("child_process")
module.exports = class MyClass {
init() {
setInterval(this.checkFileContent, 10)
}
async checkFileContent() {
await new Promise((resolve) => { exec("sleep 0.4", resolve) })
const fileContent = (await fs.promises.readFile("foo.txt")).toString()
console.log(fileContent)
}
}
and this test file
const MyClass = require(".")
const fs = require("fs")
const sinon = require("sinon")
const { exec } = require("child_process")
describe("MyClass", () => {
let sandbox
beforeAll(async () => {
sandbox = sinon.createSandbox()
await fs.writeFileSync("foo.txt", "fooContent")
})
afterAll(async () => {
await fs.unlinkSync("foo.txt")
await new Promise((resolve) => { exec("sleep 0.8", resolve) })
sandbox.verifyAndRestore()
})
test("should test MyClass", async () => {
const clock = sandbox.useFakeTimers()
const instance = new MyClass()
instance.init()
clock.next()
await Promise.resolve() // As suggested in this answer https://stackoverflow.com/a/52196951/2710714 - but doesn't seem to help at all
clock.reset()
})
})
Running the test, I'll always get ENOENT: no such file or directory, open 'foo.txt'
. The reason being that await fs.unlinkSync("foo.txt")
has already run when await fs.promises.readFile("foo.txt")
is reached.
So, I need to somehow make sure that all promises in the interval
function started by clock.next()
are resolved before the tests stops. How do I do that?
Note: In real-life, it's not about file access but database queries. And the exec("sleep ..."
is of course something artificial to replicate long-lasting operations. But the principles should be the same.
Edit: Also tried await clock.nextAsync()
- didn't help.