in reply to Re: Testing with Test::Mock::HTTP::Tiny
in thread Testing with Test::Mock::HTTP::Tiny

You need to "undump" the file contents somehow and resurrect the Perl data structure you started with. The simplest way to achieve this is by eval()'ing the text representation minus the $VAR1 = at the beginning of the string (placed there by Data::Dumper) (see the warnings at the end of this post):

Shameless plug: For many data structures, it's possible to do this more safely via my Data::Undump::PPI (see the disclaimer in Config::Perl).

However, looking at the source, it would seem the simpler solution is to just serialize Test::Mock::HTTP::Tiny->captured_data oneself in a more suitable format, perhaps JSON or YAML (AFAICT from looking at the source, the data structure doesn't look like it contains Perl objects that would pervent serialization, though at the moment I don't have the time to test).

Replies are listed 'Best First'.
Re^3: Testing with Test::Mock::HTTP::Tiny
by bliako (Abbot) on Sep 27, 2023 at 10:19 UTC
    it would seem the simpler solution is to just serialize ...

    yep, good point haukex++ as this is the easiest and most secure by far. Since I have more time:

    use strict; use warnings; use HTTP::Tiny; use Test::Mock::HTTP::Tiny; use JSON; my $http = HTTP::Tiny->new; my $resp = $http->get('http://www.way-finder.uk/'); # EDIT: it's captured_data() not mocked_data() see below #my $json_str = eval { JSON::encode_json(Test::Mock::HTTP::Tiny->mocke +d_data()) }; my $json_str = eval { JSON::encode_json(Test::Mock::HTTP::Tiny->captur +ed_data()) }; die "failed to encode json" if $@; open my $fh, '>', 'mock_html.dat'; print $fh $json_str; close $fh;

    and

    use strict; use warnings; use Test::More; use Test::Mock::HTTP::Tiny; use WWW::Crawl; use JSON; plan tests => 1; $/ = undef; open my $fh, '<', 't/mock_html.dat' or die "Can't open datafile"; my $replay = <$fh>; close $fh; $replay = eval { JSON::decode_json($replay) }; ok(!$@, "parsed JSON replay data") or BAIL_OUT($@); is(ref($replay), 'ARRAY', "parsed JSON replay data is an ARRAY"); die "Nothing to replay" unless $replay; Test::Mock::HTTP::Tiny->set_mocked_data($replay); my $crawl = WWW::Crawl->new( 'timestamp' => 'a', ); my @links = $crawl->crawl('https://www.testing.crawl', \&link); cmp_ok ( scalar @links, '==', 8, 'Correct link count'); sub link { diag ($_[0]); }

    note: eval() around JSON subs is because it dies on error last time I checked.

    bw, bliako

      Since I have more time

      Thank you...I was also thinking that JSON might be the sensible solution here.

      eval() around JSON subs is because it dies on error last time I checked

      It took a moment, but I worked that out before reading your confirmation...

      But why fully qualify the methods that are exported by default?

      $replay = eval { JSON::decode_json($replay) };
      and not
      $replay = eval { decode_json($replay) };

        But why fully qualify the methods that are exported by default?

        as a mental note to myself that this sub is from that package

      Thanks for this bliako
      For anyone stumbling this way in future, the method to create the file is captured_data, not mocked_data

      Encoding to JSON gives a nice JSON file so that bit seems to be working :)

      However, I am still getting an HTTP 599 error when I try to decode it :(

      $/ = undef; open my $fh, '<', 't/mock_html.dat' or die "Can't open datafile"; my $replay = <$fh>; close $fh; $replay = eval { decode_json($replay) }; ok ( !$@, 'Parsed JSON' ) or BAIL_OUT($@); is ( ref($replay), 'ARRAY', '$replay is an ARRAY ' ); die "Nothing to replay" unless $replay; Test::Mock::HTTP::Tiny->set_mocked_data( $replay ); diag ( Dumper (Test::Mock::HTTP::Tiny->mocked_data) ); my $crawl = WWW::Crawl->new( 'timestamp' => 'a', );

      The diag gives the full JSON object as expected but Test::Mock::HTTP::Tiny is not feeding into the HTTP::Tiny->get call.

        However, I am still getting an HTTP 599 error when I try to decode it :

        It works for me. To be sure, edit Test/Mock/HTTP/Tiny.pm (perldoc -l Test::Mock::HTTP::Tiny will tell you where this file is located) and put debugging messages after ## no critic. Just in case you haven't noticed, the return from my $resp = $http->get('http://www.way-finder.uk/'); is not an HTTP::response (which offers $resp->decoded_content) but a hash with keys headers, success, content, .... So you are looking for:

        my $content = $resp->{success} && length $resp->{content} ? $resp->{co +ntent} : undef; ok(defined $content, "got content");