2

How do I mock or stub process.argv so that it can return a specific argument?

I tried using Sinon.js like this:

beforeEach(
  () => {
    sandbox.stub(
      process.argv.slice(2)[0], 'C:\\home\\project\\assignment'
    ).value('--local');
  }
);

afterEach(
  () => {
    sandbox.restore();
  }
);

test(
  'it replace value of node argument',
  () => {
    assert(process.argv.slice(2)[0], '--local');
  }
);

But I keep getting an error that says trying to stub property 'C:\\home\\project\\assignment' of undefined.

Géry Ogam
  • 6,336
  • 4
  • 38
  • 67

3 Answers3

2

You can rebind process.argv (cf. Modify node process environment or arguments runtime):

import assert from 'node:assert/strict';
import test from 'node:test';

test.describe(
  () => {
    const originalArgv = process.argv;

    test.afterEach(
      () => {
        process.argv = originalArgv;
      }
    );

    test.test(
      () => {
        process.argv = process.argv.slice(0, 1).concat(['--local']);
        assert.equal(process.argv[1], '--local');
      }
    );
  }
);
Géry Ogam
  • 6,336
  • 4
  • 38
  • 67
Lin Du
  • 88,126
  • 95
  • 281
  • 483
0

If you prefer to modify process.argv in the tests instead of rebinding it like in @LinDu’s answer, you can save and restore process.argv by making each test work on its own* shallow copy of the original process.argv, so that the tests don’t affect one another:

import assert from 'node:assert/strict';
import test from 'node:test';

test.describe(
  () => {
    const originalArgv = process.argv;

    test.beforeEach(
      () => {
        process.argv = [...originalArgv];  // own shallow copy
      }
    );

    test.test(
      () => {
        process.argv[1] = '--local';
        assert.equal(process.argv[1], '--local');
      }
    );
  }
);

* Note that making each test work on a shared shallow copy of the original process.argv won’t work since the tests will affect one another:

// THIS CODE IS INCORRECT!

import assert from 'node:assert/strict';
import test from 'node:test';

test.describe(
  () => {
    const originalArgv = [...process.argv];  // shared shallow copy

    test.beforeEach(
      () => {
        process.argv = originalArgv;
      }
    );

    test.test(
      () => {
        process.argv[1] = '--local';
        assert.equal(process.argv[1], '--local');
      }
    );
  }
);
Géry Ogam
  • 6,336
  • 4
  • 38
  • 67
0

Many Jest users will stomp on this question so I'm posting the answer using Jest here. Since 29.x, Jest has a replaceProperty method.

    jest.replaceProperty(process, 'argv', ['what', 'ever', 'you', 'like']);

The advantage is this mock can be reverted.