Search code examples
node.jstypescriptjestjsundefinedts-jest

Why does comparing an environment variable against undefined in Jest not work as expected?


While implementing some tests in Jest to ensure that a required environment variable is defined, I ran into some strange behaviour when trying to compare the environment variable against undefined. @types/node seems to suggest that any specific environment variable is either string | undefined, however in practice it seems more complicated.

  process.env.TEST_VAR = 'TEST';

  console.log(process.env.TEST_VAR);    // TEST
  console.log(typeof process.env.TEST_VAR);    // string
  console.log(process.env.TEST_VAR === undefined);    // false
  console.log(!process.env.TEST_VAR);    // false
  console.log(process.env.TEST_VAR == undefined);    // false
  console.log(process.env.TEST_VAR === '');    // false

  process.env.TEST_VAR = '';

  console.log(process.env.TEST_VAR);    // 
  console.log(typeof process.env.TEST_VAR);    // string
  console.log(process.env.TEST_VAR === undefined);    // false
  console.log(!process.env.TEST_VAR);    // true
  console.log(process.env.TEST_VAR == undefined);    // false
  console.log(process.env.TEST_VAR === '');    // true

  process.env.TEST_VAR = undefined;

  console.log(process.env.TEST_VAR);    // undefined
  console.log(typeof process.env.TEST_VAR);    // string
  console.log(process.env.TEST_VAR === undefined);    // false
  console.log(!process.env.TEST_VAR);    // false
  console.log(process.env.TEST_VAR == undefined);    // false
  console.log(process.env.TEST_VAR === '');    // false

I know this might be pedantic, however in our particular use case there's a difference between the variable being empty, and the variable being absent. Running node on the command line, referencing any undefined environment variable actually returns undefined. Does anyone know why this is occurring? And how would someone actually test for the difference between an undefined environment variable versus an empty one?


Solution

  • This is how it is defined:

    interface Process extends EventEmitter {
      ...
      env: ProcessEnv;
      ...
    }
    interface ProcessEnv extends Dict<string> {
      TZ?: string;
    }
    interface Dict<T> {
      [key: string]: T | undefined;
    }
    

    Also in your test you got answer why you cannot compare the value with undefined.

      console.log(process.env.TEST_VAR);    // undefined
      console.log(typeof process.env.TEST_VAR);    // string
    

    As even when you wanted to put undefined there, you actually put 'undefined' instead.

    Add this to your test

        delete process.env.TEST_VAR;
        
        console.log(process.env.TEST_VAR);    // undefined
        console.log(typeof process.env.TEST_VAR);    // undefined
        console.log(process.env.TEST_VAR === undefined);    // true
        console.log(!process.env.TEST_VAR);    // true
        console.log(process.env.TEST_VAR == undefined);    // true
        console.log(process.env.TEST_VAR === '');    // false
    

    And this is how you set undefined value for environment variables