Skip to content

Instantly share code, notes, and snippets.

@dmitry-vsl
Created September 23, 2024 02:03
Show Gist options
  • Save dmitry-vsl/923505180afb03b286ec7dca15ecc958 to your computer and use it in GitHub Desktop.
Save dmitry-vsl/923505180afb03b286ec7dca15ecc958 to your computer and use it in GitHub Desktop.
Mocking with generators in JavaScript
function delay(fn) {
return function(...args) {
return [fn, args]
}
}
function a(arg) {
// performs some IO operation that have to be mocked for testing
return arg + 10
}
function b(arg) {
// performs some IO operation that have to be mocked for testing
return arg*3
}
function* calculate(arg) {
const result_from_a = yield delay(a)(arg)
const result_from_b = yield delay(b)(result_from_a * 2)
return result_from_b
}
function run(generator) {
let result
while(true) {
let {value, done} = generator.next(result)
if(done) {
return value
}
const [fn, args] = value
// TODO try, use generator.throw in catch block
result = fn(...args)
}
}
function run_expecting_effects(generator, expected_effects) {
let effect_index = 0
let result
while(true) {
let {value, done} = generator.next(result)
if(done) {
// TODO check that no more expects left
return value
}
const [fn, args] = value
const effect = expected_effects[effect_index++]
if(
fn.name != effect.name
||
JSON.stringify(effect.args) != JSON.stringify(args)
) {
console.error({fn, args, effect})
throw new Error('unexpected effect')
}
result = effect.result
}
}
console.log('run', run(calculate(3))) // returns 78
console.log(
'run_expecting_effects',
run_expecting_effects(
calculate(3),
[
{name: 'a', args: [3], result: 13},
{name: 'b', args: [26], result: 78},
]
)
) // returns 78
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment