File Coverage

File:blib/lib/App/Test/Generator/Planner/Mock.pm
Coverage:97.3%

linestmtbrancondsubtimecode
1package 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# --------------------------------------------------
15Readonly my $MOCK_SYSTEM     => 'mock_system';
16Readonly my $MOCK_CAPTURE_IO => 'capture_io';
17
18our $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
119sub 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
1501;