File Coverage

blib/lib/Test/Mock/LWP/Dispatch.pm
Criterion Covered Total %
statement 82 90 91.1
branch 31 38 81.5
condition 10 19 52.6
subroutine 14 14 100.0
pod 4 4 100.0
total 141 165 85.4


line stmt bran cond sub pod time code
1             package Test::Mock::LWP::Dispatch;
2             {
3             $Test::Mock::LWP::Dispatch::VERSION = '0.06';
4             }
5              
6 8     8   289690 use strict;
  8         20  
  8         476  
7 8     8   47 use warnings;
  8         18  
  8         1265  
8              
9             # ABSTRACT: mocks LWP::UserAgent and dispatches your requests/responses
10              
11              
12 8     8   51 use base qw(Exporter Test::MockObject);
  8         20  
  8         13907  
13              
14             our @EXPORT = qw($mock_ua);
15             our @EXPORT_OK = @EXPORT;
16             our $DEFAULT_REQUEST_HEADERS = 1;
17              
18 8     8   41965 use Carp qw(croak);
  8         20  
  8         823  
19 8     8   12942 use Data::Dumper qw();
  8         158135  
  8         359  
20 8     8   12104 use HTTP::Request;
  8         393483  
  8         368  
21 8     8   10913 use HTTP::Response;
  8         127460  
  8         440  
22 8     8   30054 use LWP::UserAgent;
  8         247930  
  8         437  
23 8     8   101 use Test::MockObject;
  8         18  
  8         103  
24              
25             our $mock_ua;
26             BEGIN {
27 8     8   11485 my $default_resp = HTTP::Response->new(404);
28              
29              
30              
31             sub simple_request {
32 30     30 1 108075 my $mo = shift;
33 30         55 my $in_req = shift;
34 30 50 33     355 $in_req = $mo->prepare_request($in_req)
35             if ( $DEFAULT_REQUEST_HEADERS && $mo->can('prepare_request') );
36              
37 30   100     6409 my $global_maps = $mock_ua->{_maps} || [];
38 30   100     97 my $local_maps = $mo->{_maps} || [];
39 30         41 my $matched_resp = $default_resp;
40 30         40 foreach my $map (@{$local_maps}, @{$global_maps}) {
  30         50  
  30         60  
41 34 100       207 next unless (defined($map));
42 32         140 my ($req, $resp) = @{$map};
  32         95  
43              
44 32 100       135 if (ref($req) eq 'HTTP::Request') {
    100          
    100          
    50          
45 4 50 33     32 $req = $mo->prepare_request($req)
46             if ( $DEFAULT_REQUEST_HEADERS && $mo->can('prepare_request') );
47 4         512 my $dd = Data::Dumper->new([$in_req]);
48 4         137 my $dd_in = Data::Dumper->new([$req]);
49 4         89 $dd->Sortkeys(1);
50 4         29 $dd_in->Sortkeys(1);
51 4 100       24 next unless ($dd_in->Dump eq $dd->Dump);
52             } elsif (ref($req) eq '') {
53 20 100       63 next unless ($in_req->uri eq $req);
54             } elsif (ref($req) eq 'Regexp') {
55 4 100       12 next unless ($in_req->uri =~ $req);
56             } elsif (ref($req) eq 'CODE') {
57 4 100       11 next unless ($req->($in_req));
58             } else {
59 0         0 warn "Unknown type of predefined request: " . ref($req);
60 0         0 next;
61             }
62              
63 18         503 $matched_resp = $resp;
64 18         35 last;
65             }
66 30 100       430 if (ref($matched_resp) eq 'HTTP::Response') {
    50          
67 25         79 return $matched_resp;
68             } elsif (ref($matched_resp) eq 'CODE') {
69 5         17 return $matched_resp->($in_req);
70             } else {
71 0         0 warn "Unknown type of predefined response: " . ref($matched_resp);
72 0         0 return $default_resp;
73             }
74             }
75              
76              
77             sub map {
78 20     20 1 25807 my $mo = shift;
79              
80 20         43 my ($req, $resp) = @_;
81 20 100 66     293 if (!defined($req) || !defined($resp)) {
82 3         48 croak "You should pass 2 arguments in map()";
83             }
84 17 100       111 if (ref($req) !~ /^(HTTP::Request|Regexp|CODE|)$/) {
85 1         11 croak "Type of request must be HTTP::Request, regexp, coderef or plain string\n";
86             }
87 16 100       104 if (ref($resp) !~ /^(HTTP::Response|CODE)$/) {
88 1         12 croak "Type of response must be HTTP::Response or coderef\n";
89             }
90              
91 15         37 my $map = [$req, $resp];
92 15         21 push @{$mo->{_maps}}, $map;
  15         63  
93 15         23 return scalar(@{$mo->{_maps}}) - 1;
  15         62  
94             }
95              
96              
97             sub unmap {
98 2     2 1 1096 my $mo = shift;
99 2         5 my $index = shift;
100 2 50 33     23 return if (!defined($index) || $index !~ /^\d+$/);
101 2 50       12 unless ($mo->{_maps}) {
102 0         0 warn "You call unmap() before any call of map()\n";
103 0         0 return;
104             }
105 2 50 33     12 if ($index < 0 || $index > (scalar(@{$mo->{_maps}}) - 1)) {
  2         13  
106 0         0 warn "Index $index is out of maps range\n";
107 0         0 return;
108             }
109 2         15 delete $mo->{_maps}->[$index];
110 2         5 return 1;
111             }
112              
113              
114             sub unmap_all {
115 2     2 1 1407 my $mo = shift;
116 2         6 $mo->{_maps} = [];
117 2         9 return 1;
118             }
119              
120 8         1225 my %mock_methods = (
121             simple_request => \&simple_request,
122             map => \&map,
123             unmap => \&unmap,
124             unmap_all => \&unmap_all,
125             );
126              
127 8         82 Test::MockObject->fake_module('LWP::UserAgent', %mock_methods);
128             # The global mock object, can be used directly, or can just create a new
129             # LWP::UserAgent object - that is mocked too.
130 8         1432 $mock_ua = LWP::UserAgent->new;
131             }
132              
133             1;
134              
135             __END__