| File: | blib/lib/App/Test/Generator/Planner/Mock.pm |
| Coverage: | 100.0% |
| line | stmt | bran | cond | sub | time | code |
|---|---|---|---|---|---|---|
| 1 | package App::Test::Generator::Planner::Mock; | |||||
| 2 | ||||||
| 3 | 11 11 11 | 64883 10 128 | use strict; | |||
| 4 | 11 11 11 | 19 4 185 | use warnings; | |||
| 5 | 11 11 11 | 17 8 203 | use Carp qw(croak); | |||
| 6 | 11 11 11 | 213 1637 1224 | 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 | # A method needing both gets an arrayref of both labels | |||||
| 13 | # â 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.41'; | |||||
| 19 | ||||||
| 20 - 60 | =head1 VERSION
Version 0.41
=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 | 17 | 96503 | 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 a mock strategy. 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>. A method needing only one of these gets that value as
a plain scalar string. A method that both calls external commands and
performs IO needs both mocks applied, so it gets an arrayref
C<[mock_system, capture_io]> instead of a single string.
=head3 API specification
=head4 input
{
self => { type => OBJECT, isa => 'App::Test::Generator::Planner::Mock' },
schema => { type => HASHREF },
}
=head4 output
{
type => HASHREF,
keys => {
'*' => { type => 'scalar | arrayref' },
},
}
=cut | |||||
| 118 | ||||||
| 119 | sub plan { | |||||
| 120 | 18 | 2294 | my ($self, $schema) = @_; | |||
| 121 | ||||||
| 122 | # Validate that schema is a hashref before iterating | |||||
| 123 | 18 | 44 | croak 'schema must be a hashref' unless ref($schema) eq 'HASH'; | |||
| 124 | ||||||
| 125 | 16 | 11 | my %mock_plan; | |||
| 126 | ||||||
| 127 | 16 16 | 12 20 | for my $method (keys %{$schema}) { | |||
| 128 | # Extract side effect analysis if present â | |||||
| 129 | # default to empty hashref if not available | |||||
| 130 | 18 | 30 | my $effects = $schema->{$method}{_analysis}{side_effects} || {}; | |||
| 131 | ||||||
| 132 | # -------------------------------------------------- | |||||
| 133 | # Assign mock strategy based on detected side effects. | |||||
| 134 | # A method needing both gets an arrayref of both labels | |||||
| 135 | # rather than silently dropping one of them. | |||||
| 136 | # -------------------------------------------------- | |||||
| 137 | 18 | 51 | if($effects->{calls_external} && $effects->{performs_io}) { | |||
| 138 | 4 | 9 | $mock_plan{$method} = [$MOCK_SYSTEM, $MOCK_CAPTURE_IO]; | |||
| 139 | } elsif($effects->{calls_external}) { | |||||
| 140 | 4 | 9 | $mock_plan{$method} = $MOCK_SYSTEM; | |||
| 141 | } elsif($effects->{performs_io}) { | |||||
| 142 | 4 | 7 | $mock_plan{$method} = $MOCK_CAPTURE_IO; | |||
| 143 | } | |||||
| 144 | # Pure methods require no mocking â omit from plan | |||||
| 145 | } | |||||
| 146 | ||||||
| 147 | 16 | 51 | return \%mock_plan; | |||
| 148 | } | |||||
| 149 | ||||||
| 150 | 1; | |||||