Search code examples
unit-testingjestjsvitest

Are you able to access a variable that has function scope when unit testing with Jest/Vitest?


Let's say we have a function, myFunction that we want to test.

myFunction.js

const myFunction = anotherFunction => {
  const x = Math.random()
  let foo

  if(x > 0.5) foo = true
  if(x < 0.5) foo = false

  anotherFunction(foo)
  return
}

export default myFunction

Is it possible to have access to the variable foo after executing the function in jest/vitest?

myFunction.test.js

import myFunction from "./myFunction.js"
import { test } from "vitest"
    
test("myFunction", () => {
  myFunction()
  //can the `foo` variable from within myFunction be accessed in this test?
})

Solution

  • One note: unit testing with MathRandom will leave undeterministic results!

    The way you want is not possible. But it can be achieved with another approach. In order to control the cases you need to control what Math.random() will return on each execution;

    I will propose some modifications to your function so that math is optionally injected from the function consumer

    const myFunction = (anotherFunction, math = Math) => {
      const x = math.random()
      let foo
    
      if(x > 0.5) foo = true
      if(x < 0.5) foo = false
    
      anotherFunction(foo)
      return
    }
    
    export default myFunction
    

    And now in the test we provide a jest mock with attached spy and dummy predictable Math random implementation. We can now inspect with what params the other function has been called.

    
    const getMathRandomMock = (result) => {
      return {
        random: () => result
      }
    }
    
    test("myFunction", () => {
      const anotherFuncMock = jest.fn();
      myFunction(anotherFuncMock, getMathRandomMock(0.4))
      expect(anotherFuncMock).toHaveBeenCalledWith(false)
    })