Reputation: 2090
I have a module B
that I want to test. This module depends on the module A
that I don't want to test. Here is an example of my package B
:
use strict;
use warnings FATAL => 'all';
use A;
package B;
sub to_test {
return A::a();
}
In my unit test, I would like to call B::to_test
but I want to manually specify what value A::a()
must return. To do that, I have written a module MockA.pm
that contains all the subs of A
to mock:
use strict;
use warnings 'FATAL' => 'all';
package Mock::A;
sub a {
return "From mock";
}
1;
I know I can easily mock A::a
using Test::MockModule
, the problem is the package A
may contain a lot of subs and Test::MockModule
lets me mock them only one by one.
How can I mock the full A
package with MockA
?
Upvotes: 1
Views: 299
Reputation: 385764
The existing answer shows how to replace parts of a module, which is quite sensible.
But if you wanted to replace the module entirely (to the point that the original doesn't even need to be installed), you can use the following:
# Use the name of the package we're mocking.
package A;
...
# Tell Perl that the module we're mocking has been loaded.
$INC{ ( __PACKAGE__ =~ s{::}{/}rg ) . '.pm' } = 1;
use MockA;
must appear before any instances of use A;
.
Upvotes: 3
Reputation: 2090
It is possible to redefine the subs defined in the package A
by the subs in MockA
. To do that, there are three conditions:
MockA
must define the same package than A
;MockA
must be included after all the inclusions of A
;redefine
must not be fatal.The file MockA.pm
can be the following:
use strict;
# No fatal error if a sub is redefined
use warnings 'FATAL' => 'all', 'NONFATAL' => 'redefine';
# Override package A
package A;
sub a {
return "From mock";
}
1;
And, in the unit test:
use B; # B includes A
use MockA; # MockA overrides A
B::to_test() # B calls MockA::a
Upvotes: 2