The only help I've found on the internet so far is this blog. Which I thought was going to get me there, but I don't think it's actually changing the values in my module. I made a sample to show what I mean.
package Module;
use 5.012;
use strict;
use warnings;
use Readonly qw( );
use parent qw(Exporter);
our @EXPORT_OK = qw(
&GetReadonly
);
our %EXPORT_TAGS = (
all => [ @EXPORT_OK ] );
Readonly::Scalar my $HOST => 'host.web.server.com';
sub GetReadonly
{
return $HOST;
}
1;
And the test code:
#!perl
use strict;
use warnings;
use Test::More 'no_plan';
use Module qw/ :all /;
is($Module::HOST, 'host.web.server.com'); # HOST == undef
my $fake_host = 'fakemail.web.server.com';
{
no warnings 'redefine';
local *Readonly::Scalar::STORE = sub { ${$_[0]} = $_[1]; };
$Module::HOST = $fake_host;
}
is(GetReadonly(), $fake_host); # Returns host.web.server.com
If I use the Module::HOST
from the blog, I get a bareword compile error.
Is there some better way to mock a Readonly for a unit test?
The blog was probably written in the old days when Readonly was implemented in pure Perl using tie. Nowadays, Readonly is implemented using XS. To make a variable not readonly anymore, you can call
Internals::SvREADONLY( $Module::HOST, 0 );
To be able to access the variable from outside of the module, it must be declared our, not my (as the blog correctly shows).
But the main question is: why do you need to test a different value in the variable, if the variable isn't supposed to be writable?