File Coverage

blib/lib/Test/ExpectAndCheck/Future.pm
Criterion Covered Total %
statement 39 40 97.5
branch 7 8 87.5
condition 2 2 100.0
subroutine 11 11 100.0
pod n/a
total 59 61 96.7


line stmt bran cond sub pod time code
1             # You may distribute under the terms of either the GNU General Public License
2             # or the Artistic License (the same terms as Perl itself)
3             #
4             # (C) Paul Evans, 2020 -- leonerd@leonerd.org.uk
5              
6             package Test::ExpectAndCheck::Future;
7              
8 2     2   64275 use strict;
  2         16  
  2         50  
9 2     2   9 use warnings;
  2         4  
  2         52  
10 2     2   8 use base qw( Test::ExpectAndCheck );
  2         4  
  2         564  
11              
12             our $VERSION = '0.03';
13              
14 2     2   14 use constant EXPECTATION_CLASS => "Test::ExpectAndCheck::Future::_Expectation";
  2         2  
  2         137  
15              
16             =head1 NAME
17              
18             C - C-style unit testing with C-returning methods
19              
20             =head1 SYNOPSIS
21              
22             use Test::More;
23             use Test::ExpectAndCheck::Future;
24              
25             my ( $controller, $puppet ) = Test::ExpectAndCheck::Future->create;
26              
27             {
28             $controller->expect( act => 123, 45 )
29             ->returns( 678 );
30              
31             is( $puppet->act( 123, 45 )->get, 678, '$puppet->act yields result' );
32              
33             $controller->check_and_clear( '->act' );
34             }
35              
36             done_testing;
37              
38             =head1 DESCRIPTION
39              
40             This package creates objects that assist in writing unit tests with mocked
41             object instances. Each mocked "puppet" instance will expect to receive a given
42             list of method calls. Each method call is checked that it received the right
43             arguments, and will return a L instance to yield the prescribed
44             result. At the end of each test, each object is checked to ensure all the
45             expected methods were called.
46              
47             It is a variation of L, assistance around the results
48             of invoked methods. Every invoked method will return a L instance. The
49             L or L method can then set the desired eventual result of
50             that future instance for each expectation.
51              
52             These return instances are implemented using L, so
53             they are not immediately ready. Instead they will only become ready after a
54             toplevel C expression or call to the C method. This should help
55             unit tests to run similarly to real-world behaviour, where most futures
56             returned by real-world interfaces (such as IO systems) would not be
57             immediately ready. This behaviour can be switched off for individual
58             expectations by using the L method.
59              
60             =cut
61              
62             package
63             Test::ExpectAndCheck::Future::_Expectation;
64 2     2   11 use base qw( Test::ExpectAndCheck::_Expectation );
  2         2  
  2         633  
65              
66 2     2   890 use Test::Future::Deferred;
  2         22813  
  2         74  
67              
68             use constant {
69 2         483 RETURNS => 5,
70             FAILURE => 8,
71             BEHAVIOUR => 9,
72 2     2   15 };
  2         4  
73              
74             =head1 EXPECTATIONS
75              
76             =head2 returns
77              
78             $exp->returns( @result )
79              
80             Sets the result that the future returned by this method call will yield.
81              
82             =cut
83              
84             =head2 fails
85              
86             $exp->fails( $message )
87             $exp->fails( $message, $category, @details )
88              
89             Sets the failure that the future returned by this method call will yield.
90              
91             =cut
92              
93             sub fails
94             {
95 1     1   2 my $self = shift;
96              
97 1         4 $self->[FAILURE] = [ @_ ];
98              
99 1         2 return $self;
100             }
101              
102             =head2 immediately
103              
104             $exp->returns( ... )->immediately
105              
106             $exp->fails( ... )->immediately
107              
108             Switches this expectation to return an immediate future, rather than a
109             deferred one.
110              
111             =cut
112              
113             sub immediately
114             {
115 1     1   4 my $self = shift;
116              
117 1         4 $self->[BEHAVIOUR] = "immediate";
118             }
119              
120             =head2 remains_pending
121              
122             $exp->remains_pending
123              
124             Sets that the future returned by this method will not complete and simply
125             remain pending.
126              
127             =cut
128              
129             sub remains_pending
130             {
131 1     1   3 my $self = shift;
132              
133 1         3 $self->[BEHAVIOUR] = "pending";
134             }
135              
136             sub _result
137             {
138 5     5   12 my $self = shift;
139              
140 5   100     23 my $behaviour = $self->[BEHAVIOUR] // "";
141              
142 5 100       24 if( $behaviour eq "pending" ) {
    100          
143 1         9 return Future->new;
144             }
145             elsif( $behaviour eq "immediate" ) {
146 1 50       6 return Future->fail( @{ $self->[FAILURE] } ) if $self->[FAILURE];
  0         0  
147 1         3 return Future->done( @{ $self->[RETURNS] } );
  1         11  
148             }
149             else {
150 3 100       11 return Test::Future::Deferred->fail_later( @{ $self->[FAILURE] } ) if $self->[FAILURE];
  1         8  
151 2         4 return Test::Future::Deferred->done_later( @{ $self->[RETURNS] } );
  2         21  
152             }
153             }
154              
155             =head1 AUTHOR
156              
157             Paul Evans
158              
159             =cut
160              
161             0x55AA;