2009-07-15 50 views
3

我們的網絡應用程序與幾個我們無法影響的網絡服務一起工作。在每個工作流程(使用Selenium進行測試)之後,會發生對Web服務的掛接調用。我想嘲笑那臺服務器。理想情況下,我需要一個HTTP服務器對象,我可以隨意啓動並殺死它,還有一個URL調度程序,它可以在調用時在我的測試中調用某些子例程。如何在Perl中模擬Web服務器?

到目前爲止,我發現HTTP::Server::SimpleHTTP::Server::Brick,我發現後者更吸引人。你有其他的內幕消息嗎?

+0

催化劑也做到這一點。 – 2009-07-15 20:39:58

回答

0

Net::HTTPServer非常靈活,比較成熟。

它可以基於URL路徑調用subs。

4

我使用了HTTP :: Daemon和Template :: Toolkit的組合來執行此操作。


package Test::WebService; 

use HTTP::Daemon; 
use HTTP::Response; 
use IO::File; 
use Template; 

our $PID = $$; 

END { __PACKAGE__->StopWeb(); } 

sub StartWeb : method { 

    my $self = shift; 
    my $port = shift; 
    my %actions = $_[0] && ref($_[0]) eq 'HASH' ? %{ $_[0] } : @_ %2 ?() : @_; 

    # Ignore CHLD 
    local $SIG{CHLD} = 'IGNORE'; 

    # Fork 
    my $pid = fork(); 

    if ($pid == 0) 
    { 
     # Create pid file 
     _createPid("/tmp/httpd.pid"); 

     # Create server 
     eval 
     { 
      # Create socket 
      my $d = HTTP::Daemon->new 
      (
       Listen  => 1, 
       LocalPort => $port, 
       Reuse  => 1, 
      ) || die "Failed to bind socket"; 

      # Listen for connections 
      while (my $c = $d->accept) 
      { 
       # Process requests 
       while (my $r = $c->get_request()) 
       {    
        if (defined(my $tmpl = $actions{ $r->uri()->path() })) 
        { 
         eval 
         { 
          # Create template object 
          my $tt = Template->new({ABSOLUTE => 1 }); 

          # Create response 
          my $rs = HTTP::Response->new('200'); 

          # Process template 
          $tt->process 
          (
           $tmpl, 
           $r->uri()->query_form_hash(), 
           sub { $rs->content(shift) } 
          ); 

          # Send response 
          $c->send_response($rs); 
         }; 

         if ([email protected]) 
         { 
          $c->send_error('500', [email protected]); 
         } 

        } 
        else 
        { 
         $c->send_error('404', 'No Template Found'); 
        } 
       } 
      } 
     }; 

     if ([email protected]) 
     { 
      # Remove pid file 
      unlink "/tmp/httpd.pid"; 

      # die 
      die [email protected]; 
     } 

     # Exit nicely 
     exit(0); 
    } 

    # Wait up to 5 seconds for server to start; 
    die "Failed to start http server" unless _waitpid(5, "/tmp/httpd.pid"); 

} 

sub StopWeb { 

    # Only cleanup parent process. 
    if ($PID && $PID == $$) 
    { 
     if (my $fh = IO::File->new("/tmp/httpd.pid", 'r')) 
     { 
      # Get pid. 
      my $pid; 
      $fh->read($pid, 16384); 
      $pid =~ s/\D//g; 

      # Kill server 
      kill 4, $pid if $pid; 
     } 
    } 
} 

sub _createPid { 

    my $fh = IO::File->new(shift, 'w') || die "Couldn't create pid"; 
    $fh->print("$$"); 
    $fh->close(); 

    return; 
} 

sub _waitpid { 

    my $secs = shift || 5; 
    my $file = shift || die "Missing pid file"; 

    for(my $i=0; $i

測試代碼然後可以這樣寫:

 
#!/usr/bin/perl 

use Test::More tests => 1; 
use Test::WebService; 

use MyApp; 

Test::WebService->StartWeb('8088', '/webservice/method' => 'my.tmpl'); 

ok (MyApp->methodThatCallsWebService(), 'yay!'); 

1;