Stories
Slash Boxes
Comments
NOTE: use Perl; is on undef hiatus. You can read content, but you can't post it. More info will be forthcoming forthcomingly.

All the Perl that's Practical to Extract and Report

use Perl Log In

Log In

[ Create a new account ]

Ovid (2709)

Ovid
  (email not shown publicly)
http://publius-ovidius.livejournal.com/
AOL IM: ovidperl (Add Buddy, Send Message)

Stuff with the Perl Foundation. A couple of patches in the Perl core. A few CPAN modules. That about sums it up.

Journal of Ovid (2709)

Friday October 15, 2004
06:03 PM

Neat SOAP::Lite mock interface hack

[ #21363 ]

In order to isolate some behavior in my SOAP::Lite tests, I wanted to ensure two things. First, I wanted to know that the SOAP request XML matched my expectations. Second, I wanted to ensure that the SOAP response XML was correctly parsed. In neither case did I want to actually make the round-trip to our customer's SOAP server.

package MOCK::SOAP::INTERFACE;
use Sub::Override;

use overload
    '""' => \&request;

my $REQUEST; # this is the SOAP *request* XML

sub _mock_soap_interface
{
    my $xml   = shift; # this is the SOAP *response* XML
    my $token = Sub::Override->new(
        'SOAP::Lite::call',
        sub {
            my $self = shift;
            $REQUEST = $self->serializer->envelope(method => shift(@_), @_);
            return $xml;
        }
    );
    bless $token => __PACKAGE__;
    return $token;
}

sub request { return $REQUEST }

1;

Because overridden subs from Sub::Override are lexically scoped, the caller has to hold onto the returned token in order to keep it in scope. By blessing that token into my mocked class, I can then overload stringification and allow it to represent the SOAP request XML that &SOAP::Serializer::envelope returns. Then I write my test something like this:

sub test_my_soap : Test(2) {
    my $xml = <<'END_XML';
<?xml version="1.0" encoding="utf-8"?>
<!-- add valid soap envelope here.
     This should be what the SOAP server *returns* -->
END_XML

    my %expected_circuits = (
        # some data
    );
    my $expected_xml = # expected *request* XML
    my $response     = _mock_soap_interface($xml);
    my $soap         = MY::SOAP::Package->new;

    my $circuits = $soap->get_circuits;

    is_deeply(
        $circuits,
        \%expected_circuits
    );
    # quote response to break the overloading
    is_xml("$response", $expected_xml);
}

Yeah, there's some hackish stuff there, but one thing I really like is that now, when you're reading the tests, the programmer is much more likely to remember to hold on to the returned token ($response). Still, it looks weird having a scalar who's value is going to change for no apparent reason. I can't say that I totally like this approach, but I was pretty durned pleased with myself.

I think that I might just have to offer some sort of overloading support for Sub::Override so that the returned token actually does something useful.

The Fine Print: The following comments are owned by whoever posted them. We are not responsible for them in any way.
 Full
 Abbreviated
 Hidden
More | Login | Reply
Loading... please wait.