Yamikuronue
Yamikuronue

Reputation: 758

MockModule's mock not being called?

I have a module that uses random numbers in it. For testing purposes, I want to set the random number generator to provide a given number before it's called. My code under test includes the dependency like so:

use Math::Random::MT qw(rand);

And uses it like so:

my $currdice = int(rand($right) + 1);

And my mocking is done like so:

my $mockRand;
BEGIN {
    $mockRand = Test::MockModule->new('Math::Random::MT');
    use_ok(LogiDice);
}
$mockRand->mock('rand' => sub {return 1});
($successes, $output) = LogiDice::roll("3d10","ww");
ok($successes == 0, "WhiteWolf mode can return 0 successes") or diag ("Reported " . $successes . " successes instead.");

I'm getting random numbers of successes instead of always getting 0 (since the random number should always be 1, which should always be a failure). Is this something to do with how I did qw(rand)? Am I using MockModule incorrectly? Should I be using MockModule at all? I tried MockObject before I found MockModule but that wasn't working either.

Upvotes: 0

Views: 181

Answers (1)

Rednaxela
Rednaxela

Reputation: 106

So, what I think happens is...

  1. You make your mock wrapper
  2. Then you call "use_ok(LogiDice)", which triggers "Math::Random::MT qw(rand);" and immediately pulls a copy of "rand" into it's own namespace
  3. Your mock call replaces MT::rand (but not affecting which already has a direct reference to the old "rand")

It would probably work if you move "use_ok" after your call to mock "rand". Alternatively, one could make LogiDice not import "rand" into it's own namespace, and always refer to MT::rand.

Upvotes: 2

Related Questions