| File: | blib/lib/App/Test/Generator/Planner/Mock.pm |
| Coverage: | 97.3% |
| line | stmt | bran | cond | sub | time | code |
|---|---|---|---|---|---|---|
| 1 | package App::Test::Generator::Planner::Mock; | |||||
| 2 | ||||||
| 3 | 8 8 8 | 65192 6 95 | use strict; | |||
| 4 | 8 8 8 | 13 5 141 | use warnings; | |||
| 5 | 8 8 8 | 11 7 126 | use Carp qw(croak); | |||
| 6 | 8 8 8 | 205 1676 830 | use Readonly; | |||
| 7 | ||||||
| 8 | # -------------------------------------------------- | |||||
| 9 | # Mock strategy labels written to the plan output. | |||||
| 10 | # mock_system is used when a method calls external | |||||
| 11 | # commands; capture_io when it performs IO operations. | |||||
| 12 | # Note: if a method does both, mock_system takes | |||||
| 13 | # precedence â see note in plan() below. | |||||
| 14 | # -------------------------------------------------- | |||||
| 15 | Readonly my $MOCK_SYSTEM => 'mock_system'; | |||||
| 16 | Readonly my $MOCK_CAPTURE_IO => 'capture_io'; | |||||
| 17 | ||||||
| 18 | our $VERSION = '0.36'; | |||||
| 19 | ||||||
| 20 - 60 | =head1 VERSION
Version 0.36
=head1 DESCRIPTION
Plans mock strategy for each method that has external side effects,
based on side effect analysis metadata in the schema. Methods that
call external commands are assigned a system mock; methods that
perform IO are assigned IO capture. Used by
L<App::Test::Generator::Emitter::Perl> to generate appropriate mock
setup code in the test output.
=head2 new
Construct a new Mock planner.
my $planner = App::Test::Generator::Planner::Mock->new;
=head3 Arguments
None.
=head3 Returns
A blessed hashref.
=head3 API specification
=head4 input
{}
=head4 output
{
type => OBJECT,
isa => 'App::Test::Generator::Planner::Mock',
}
=cut | |||||
| 61 | ||||||
| 62 | 14 | 93975 | sub new { bless {}, shift } | |||
| 63 | ||||||
| 64 - 117 | =head2 plan
Produce a mock plan for each method that requires external mocking,
based on side effect analysis metadata in the schema.
my $planner = App::Test::Generator::Planner::Mock->new;
my $mock_plan = $planner->plan($schema);
for my $method (keys %{$mock_plan}) {
printf "%s: %s\n", $method, $mock_plan->{$method};
}
=head3 Arguments
=over 4
=item * C<$schema>
A hashref of method schemas, each optionally containing a
C<_analysis> key with a C<side_effects> sub-key as produced by
L<App::Test::Generator::Analyzer::SideEffect>.
=back
=head3 Returns
A hashref mapping method names to mock strategy strings. Only methods
that require mocking appear in the output â pure methods are omitted.
Currently supported strategy values are C<mock_system> and
C<capture_io>. If a method both calls external commands and performs
IO, C<mock_system> takes precedence. This is a known limitation and
may be revised in a future version to support multiple strategies per
method.
=head3 API specification
=head4 input
{
self => { type => OBJECT, isa => 'App::Test::Generator::Planner::Mock' },
schema => { type => HASHREF },
}
=head4 output
{
type => HASHREF,
keys => {
'*' => { type => SCALAR },
},
}
=cut | |||||
| 118 | ||||||
| 119 | sub plan { | |||||
| 120 | 13 | 238 | my ($self, $schema) = @_; | |||
| 121 | ||||||
| 122 | # Validate that schema is a hashref before iterating | |||||
| 123 | 13 | 25 | croak 'schema must be a hashref' unless ref($schema) eq 'HASH'; | |||
| 124 | ||||||
| 125 | 12 | 7 | my %mock_plan; | |||
| 126 | ||||||
| 127 | 12 12 | 10 12 | for my $method (keys %{$schema}) { | |||
| 128 | # Extract side effect analysis if present â | |||||
| 129 | # default to empty hashref if not available | |||||
| 130 | 12 | 15 | my $effects = $schema->{$method}{_analysis}{side_effects} || {}; | |||
| 131 | ||||||
| 132 | # -------------------------------------------------- | |||||
| 133 | # Assign mock strategy based on detected side effects. | |||||
| 134 | # mock_system takes precedence over capture_io when | |||||
| 135 | # both are present â this is a known limitation. | |||||
| 136 | # TODO: consider supporting multiple strategies per | |||||
| 137 | # method as an arrayref in a future version. | |||||
| 138 | # -------------------------------------------------- | |||||
| 139 | 12 | 17 | if($effects->{calls_external}) { | |||
| 140 | 6 | 8 | $mock_plan{$method} = $MOCK_SYSTEM; | |||
| 141 | } elsif($effects->{performs_io}) { | |||||
| 142 | 3 | 6 | $mock_plan{$method} = $MOCK_CAPTURE_IO; | |||
| 143 | } | |||||
| 144 | # Pure methods require no mocking â omit from plan | |||||
| 145 | } | |||||
| 146 | ||||||
| 147 | 12 | 29 | return \%mock_plan; | |||
| 148 | } | |||||
| 149 | ||||||
| 150 | 1; | |||||