Is there a way to override a Perl "use constant" in your unit testing?

compile-time-constant, constants, mocking, perl, unit-testing

Solution

When using constants they are implemented as constant functions behaving something like:

use subs 'BASE_PATH';
sub BASE_PATH () {"/data/monitor/"}

Any uses of BASE_PATH in the program are inlined and so can't be modified.

To achieve similar you could manually use the subs pragma (to make BASE_PATH behave as a built in function) and declare BASE_PATH as a standard function:

use subs 'BASE_PATH';
sub BASE_PATH {"/data/monitor/"}

print "BASE_PATH is ".BASE_PATH."\n";

*BASE_PATH = sub {"/new/path"};
print "BASE_PATH is ".BASE_PATH."\n";

Although why you would want to do this I'm not too sure.

Problem

I have a Perl module that I have declared some constants: ``` use constant BASE_PATH => "/data/monitor/"; ``` In live operation the constant will never change but I wish to be able to modify it in my unit tests, e.g. to set it to `~/project/testdata/`. Is there a way do do this without having to use global mutable variables? Could I possibly use `Test::MockObject` on the `constant`?

Original source