`MockFunctionContext` cannot be used to track callback / continuation-passing methods
Dieses Issue hat noch niemand übernommen.
- Vorherrschende Sprache
- JavaScript
- Sterne
- 122k
- Forks
- 37.3k
- Ø Merge
- 4 T. 2 Std.
- Gemergte PRs (30 T.)
- 283
Beschreibung
Version
v22.14.0
Platform
Darwin MacBookPro 24.4.0 Darwin Kernel Version 24.4.0: Fri Apr 11 18:28:23 PDT 2025; root:xnu-11417.101.15~117/RELEASE_X86_64 x86_64
Subsystem
node:test
What steps will reproduce the bug?
Consider the following test:
let fs = require('node:fs')
function writer (cb) {
console.log('calling fs.writeFile')
fs.writeFile('test.test', 'hi', cb)
}
let { test } = require('node:test')
test('callback test mocking not working?', (t, done) => {
console.log('mocking fs.writeFile')
t.mock.method(fs, 'writeFile', (dest, data, cb) => {
console.log('mock writeFile executing, calling back')
cb()
})
writer(err => {
if (err) console.warn('got a writeFile error', err)
console.log('fs.writeFile mock callcount:', fs.writeFile.mock.callCount())
done()
})
})
When I run the above test, the call count on the mocked method is 0, even though the console.log from within the mocked method is output:
➜ node --test callback-test.js
mocking fs.writeFile
calling fs.writeFile
mock writeFile executing, calling back
fs.writeFile mock callcount: 0
✔ callback test mocking not working? (1.868146ms)
ℹ tests 1
ℹ suites 0
ℹ pass 1
ℹ fail 0
ℹ cancelled 0
ℹ skipped 0
ℹ todo 0
ℹ duration_ms 79.29258
How often does it reproduce? Is there a required condition?
Every time.
What is the expected behavior? Why is that the expected behavior?
I would expect that the call count for the mocked method is 1 in the above test. If the test method provides an optional done callback parameter, that signaled to me that node:test could be used to test continuation-passing style of source code.
What do you see instead?
Instead, call count is 0:
➜ node --test callback-test.js
mocking fs.writeFile
calling fs.writeFile
mock writeFile executing, calling back
fs.writeFile mock callcount: 0
✔ callback test mocking not working? (1.868146ms)
ℹ tests 1
ℹ suites 0
ℹ pass 1
ℹ fail 0
ℹ cancelled 0
ℹ skipped 0
ℹ todo 0
ℹ duration_ms 79.29258
Additional information
I am in the process of updating old modules - several years old and that have worked just fine since about 2017 - and removing third party test frameworks and moving to the native node test runner module (node:test). These modules are written in this continuation-passing style - functions that accept a callback.
I suppose the entire chain of callbacks (not sure what term to use for this) must complete before the mock method records a call? The event loop must complete a lap before the method tracking is registered? If I extend the test in my example with a promisified version, then my expectations are met:
let fs = require('node:fs')
let { promisify } = require('node:util')
function writer (cb) {
console.log('calling fs.writeFile')
fs.writeFile('test.test', 'hi', cb)
}
let promisifiedWriter = promisify(writer)
let { test } = require('node:test')
test('callback test mocking not working?', (t, done) => {
console.log('mocking fs.writeFile')
t.mock.method(fs, 'writeFile', (dest, data, cb) => {
console.log('mock writeFile executing, calling back')
cb()
})
writer(err => {
if (err) console.warn('got a writeFile error', err)
console.log('fs.writeFile mock callcount:', fs.writeFile.mock.callCount())
done()
})
})
test('promisified test mocking working', async (t) => {
console.log('mocking fs.writeFile')
t.mock.method(fs, 'writeFile', (dest, data, cb) => {
console.log('mock writeFile executing, calling back')
cb()
})
await promisifiedWriter()
console.log('fs.writeFile mock callcount:', fs.writeFile.mock.callCount())
})
➜ node --test callback-test.js
mocking fs.writeFile
calling fs.writeFile
mock writeFile executing, calling back
fs.writeFile mock callcount: 0
mocking fs.writeFile
calling fs.writeFile
mock writeFile executing, calling back
fs.writeFile mock callcount: 1
✔ callback test mocking not working? (1.858847ms)
✔ promisified test mocking working (0.314972ms)
Beitragsleitfaden
Erste Schritte
- Lies das ganze Issue und danach den Beitragsleitfaden des Projekts.
- Schreib ins Issue, dass du es übernimmst — das erspart doppelte Arbeit.
- Forke das Repository und arbeite in einem Branch.
- Öffne einen Pull Request, der die Issue-Nummer nennt.
Rechercherichtung
Beginne mit dem Verhalten von node:test MockFunctionContext und reproduziere das Problem mit callback-test.js unter Verwendung von node --test. Verfolge den Mock-Pfad von fs.writeFile auf Callback-Basis und sorge dafür, dass der Callback-Test eine Aufrufanzahl von 1 meldet. Führe anschließend sowohl die Callback- als auch die promisifizierten Beispiele erneut aus, um ihre erwarteten Ergebnisse zu bestätigen.
Vom Indexierungsmodell aus dem Issue-Text verfasst.
Bewertung
- Tech-Stack
- javascript, node.js
- Bereich
- testing
- Issue-Typ
- Bug
- Schwierigkeit
- 4/5
- Geschätzter Aufwand
- 3-5 Tage
- Aktivitätsstatus
- Ruhig
- Klarheit
- Größtenteils klar
- Anfängerfreundlichkeit
- 45/100