<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
		>
<channel>
	<title>Comments on: Ruby Mock Web Server</title>
	<atom:link href="http://dynamicorange.com/2009/02/18/ruby-mock-web-server/feed/" rel="self" type="application/rss+xml" />
	<link>http://dynamicorange.com/2009/02/18/ruby-mock-web-server/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=ruby-mock-web-server</link>
	<description>A low-frequency blog by Rob Styles</description>
	<lastBuildDate>Mon, 19 Dec 2011 07:54:25 +0000</lastBuildDate>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
	<item>
		<title>By: links for 2011-05-25 &#171; Bloggitation</title>
		<link>http://dynamicorange.com/2009/02/18/ruby-mock-web-server/#comment-4551</link>
		<dc:creator>links for 2011-05-25 &#171; Bloggitation</dc:creator>
		<pubDate>Thu, 26 May 2011 06:04:27 +0000</pubDate>
		<guid isPermaLink="false">http://dynamicorange.com/?p=447#comment-4551</guid>
		<description>[...] Ruby Mock Web Server (tags: ruby rack programming via:zite) [...]</description>
		<content:encoded><![CDATA[<p>[...] Ruby Mock Web Server (tags: ruby rack programming via:zite) [...]</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Rob Styles</title>
		<link>http://dynamicorange.com/2009/02/18/ruby-mock-web-server/#comment-4550</link>
		<dc:creator>Rob Styles</dc:creator>
		<pubDate>Mon, 18 Jan 2010 11:06:45 +0000</pubDate>
		<guid isPermaLink="false">http://dynamicorange.com/?p=447#comment-4550</guid>
		<description>Great suggestions folks, thanks - nice ideas to think about.</description>
		<content:encoded><![CDATA[<p>Great suggestions folks, thanks &#8211; nice ideas to think about.</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: hedgehog</title>
		<link>http://dynamicorange.com/2009/02/18/ruby-mock-web-server/#comment-4549</link>
		<dc:creator>hedgehog</dc:creator>
		<pubDate>Sat, 16 Jan 2010 09:42:58 +0000</pubDate>
		<guid isPermaLink="false">http://dynamicorange.com/?p=447#comment-4549</guid>
		<description>I&#039;d like to recant some the Rack::Test comments I made.  After digging into the code I shuddered. Whetever you are exercising/testing with Rack::Test it is very likely not what you are running in production. My context was an asyncronous server and it was a nightmare.  It might suffice for synchronous server code?</description>
		<content:encoded><![CDATA[<p>I&#8217;d like to recant some the Rack::Test comments I made.  After digging into the code I shuddered. Whetever you are exercising/testing with Rack::Test it is very likely not what you are running in production. My context was an asyncronous server and it was a nightmare.  It might suffice for synchronous server code?</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: hedgehog</title>
		<link>http://dynamicorange.com/2009/02/18/ruby-mock-web-server/#comment-4548</link>
		<dc:creator>hedgehog</dc:creator>
		<pubDate>Wed, 13 Jan 2010 05:45:46 +0000</pubDate>
		<guid isPermaLink="false">http://dynamicorange.com/?p=447#comment-4548</guid>
		<description>Hi This got me thinkering and tinkering today. I&#039;m curious about one thing.  It seems a (unstated) requirement is that you can&#039;t use an existing framework, such as Sinatra, or another?  Otherwise this would be a few lines in the RSpec&#039;s before(:all) and specing Rack&#039;s last_response contents. Or have I misunderstood the constraints/requirements?

@Chris Tierney:  How do you invoke http://localhost:4000/foo so that MockServer#call method is given the right data? Sinatra gave me grief and ended up just using Rack::Test.  Seems much simpler, exercieses the route and all I can see is that the MockServer call is never invoked - puzzled.</description>
		<content:encoded><![CDATA[<p>Hi This got me thinkering and tinkering today. I&#8217;m curious about one thing.  It seems a (unstated) requirement is that you can&#8217;t use an existing framework, such as Sinatra, or another?  Otherwise this would be a few lines in the RSpec&#8217;s before(:all) and specing Rack&#8217;s last_response contents. Or have I misunderstood the constraints/requirements?</p>
<p>@Chris Tierney:  How do you invoke <a href="http://localhost:4000/foo" rel="nofollow">http://localhost:4000/foo</a> so that MockServer#call method is given the right data? Sinatra gave me grief and ended up just using Rack::Test.  Seems much simpler, exercieses the route and all I can see is that the MockServer call is never invoked &#8211; puzzled.</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Chris Tierney</title>
		<link>http://dynamicorange.com/2009/02/18/ruby-mock-web-server/#comment-4547</link>
		<dc:creator>Chris Tierney</dc:creator>
		<pubDate>Fri, 21 Aug 2009 11:19:11 +0000</pubDate>
		<guid isPermaLink="false">http://dynamicorange.com/?p=447#comment-4547</guid>
		<description>My apologies. The two of the comment lines should be swapped:

# my_code_that_should_make_post_request # to http://localhost:4000/foo
# request_received.should be_true</description>
		<content:encoded><![CDATA[<p>My apologies. The two of the comment lines should be swapped:</p>
<p># my_code_that_should_make_post_request # to <a href="http://localhost:4000/foo" rel="nofollow">http://localhost:4000/foo</a><br />
# request_received.should be_true</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Chris Tierney</title>
		<link>http://dynamicorange.com/2009/02/18/ruby-mock-web-server/#comment-4546</link>
		<dc:creator>Chris Tierney</dc:creator>
		<pubDate>Fri, 21 Aug 2009 10:56:41 +0000</pubDate>
		<guid isPermaLink="false">http://dynamicorange.com/?p=447#comment-4546</guid>
		<description>Thanks for this! Here&#039;s my attempt:
- make the mock *less* clever, put the logic you require in your specs
- eg. move testing of expectations and (programmatic) creation of rack response back into the test code using a supplied block
- ensure exceptions in the server thread (perhaps from expectations failing in your block) are passed back to the thread running the tests, so that the tests then fail.

Tested informally on Ruby 1.9.1
I&#039;ve only used it a little so far, so I&#039;m unsure how much mileage I will get with this approach. Here&#039;s the code:


#
require &#039;rack&#039;

#
## Bring up server in a new thread (do once?):
# @mock_server = MockServer.new(4000, 0.5)
#
#
## Pull down server:
# @mock_server.stop
#
#
## Expectations (rspec example):
# request_received = false
# @mock_server.attach do &#124;env&#124;
#   request_received = true
#   env[&#039;REQUEST_METHOD&#039;].should == &#039;POST&#039;
#   env[&#039;PATH_INFO&#039;].should == &#039;/foo&#039;
#   [ 200, { &#039;Content-Type&#039; =&gt; &#039;text/plain&#039;, &#039;Content-Length&#039; =&gt; &#039;40&#039; }, [ &#039;This gets returned from the HTTP request&#039; ]]
# end
# request_received.should be_true
# my_code_that_should_make_post_request # to http://localhost:4000/foo
#
#
## After each test:
# @mock_server.detach
#
#

class MockServer
  def initialize(port = 4000, pause = 1)
    @block = nil
    @parent_thread = Thread.current
    @thread = Thread.new do
      Rack::Handler::WEBrick.run(self, :Port =&gt; port)
    end

    sleep pause # give the server time to fire up... YUK!
  end

  def stop
    Thread.kill(@thread)
  end

  def attach(&amp;block)
    @block = block
  end

  def detach()
    @block = nil
  end

  def call(env)
    begin
      raise &quot;Specify a handler for the request using attach(block), the block should return a valid rack response and can test expectations&quot; unless @block
      @block.call(env)
    rescue Exception =&gt; e
      @parent_thread.raise e
      [ 500, { &#039;Content-Type&#039; =&gt; &#039;text/plain&#039;, &#039;Content-Length&#039; =&gt; &#039;13&#039; }, [ &#039;Bad test code&#039; ]]
    end
  end
end</description>
		<content:encoded><![CDATA[<p>Thanks for this! Here&#8217;s my attempt:<br />
- make the mock *less* clever, put the logic you require in your specs<br />
- eg. move testing of expectations and (programmatic) creation of rack response back into the test code using a supplied block<br />
- ensure exceptions in the server thread (perhaps from expectations failing in your block) are passed back to the thread running the tests, so that the tests then fail.</p>
<p>Tested informally on Ruby 1.9.1<br />
I&#8217;ve only used it a little so far, so I&#8217;m unsure how much mileage I will get with this approach. Here&#8217;s the code:</p>
<p>#<br />
require &#8216;rack&#8217;</p>
<p>#<br />
## Bring up server in a new thread (do once?):<br />
# @mock_server = MockServer.new(4000, 0.5)<br />
#<br />
#<br />
## Pull down server:<br />
# @mock_server.stop<br />
#<br />
#<br />
## Expectations (rspec example):<br />
# request_received = false<br />
# @mock_server.attach do |env|<br />
#   request_received = true<br />
#   env['REQUEST_METHOD'].should == &#8216;POST&#8217;<br />
#   env['PATH_INFO'].should == &#8216;/foo&#8217;<br />
#   [ 200, { 'Content-Type' =&gt; 'text/plain', 'Content-Length' =&gt; '40' }, [ 'This gets returned from the HTTP request' ]]<br />
# end<br />
# request_received.should be_true<br />
# my_code_that_should_make_post_request # to <a href="http://localhost:4000/foo" rel="nofollow">http://localhost:4000/foo</a><br />
#<br />
#<br />
## After each test:<br />
# @mock_server.detach<br />
#<br />
#</p>
<p>class MockServer<br />
  def initialize(port = 4000, pause = 1)<br />
    @block = nil<br />
    @parent_thread = Thread.current<br />
    @thread = Thread.new do<br />
      Rack::Handler::WEBrick.run(self, <img src='http://dynamicorange.com/wp-includes/images/smilies/icon_razz.gif' alt=':P' class='wp-smiley' /> ort =&gt; port)<br />
    end</p>
<p>    sleep pause # give the server time to fire up&#8230; YUK!<br />
  end</p>
<p>  def stop<br />
    Thread.kill(@thread)<br />
  end</p>
<p>  def attach(&amp;block)<br />
    @block = block<br />
  end</p>
<p>  def detach()<br />
    @block = nil<br />
  end</p>
<p>  def call(env)<br />
    begin<br />
      raise &#8220;Specify a handler for the request using attach(block), the block should return a valid rack response and can test expectations&#8221; unless @block<br />
      @block.call(env)<br />
    rescue Exception =&gt; e<br />
      @parent_thread.raise e<br />
      [ 500, { 'Content-Type' =&gt; 'text/plain', 'Content-Length' =&gt; '13' }, [ 'Bad test code' ]]<br />
    end<br />
  end<br />
end</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Elliot Smith</title>
		<link>http://dynamicorange.com/2009/02/18/ruby-mock-web-server/#comment-4545</link>
		<dc:creator>Elliot Smith</dc:creator>
		<pubDate>Thu, 05 Mar 2009 15:06:14 +0000</pubDate>
		<guid isPermaLink="false">http://dynamicorange.com/?p=447#comment-4545</guid>
		<description>Bad, bad me. My code had an error in it. Fixed in this version:

&lt;code&gt;require &#039;rubygems&#039;
require &#039;rack&#039;
require &#039;thin&#039;

# Mock server for testing bad or heavyweight server responses; runs on localhost:4000 by default
#
# Example of use
#
#  In setup method:
#
#    @mock_server = MockServer.new   # creating a new instance spawns a thread running the TCP server
#    @mock_server.register( { &#039;REQUEST_METHOD&#039; =&gt; &#039;GET&#039; }, [ 200, { &#039;Content-Type&#039; =&gt; &#039;text/plain&#039;, &#039;Content-Length&#039; =&gt; &#039;11&#039; }, [ &#039;Hello World&#039; ]])
#    @mock_server.register( { &#039;REQUEST_METHOD&#039; =&gt; &#039;GET&#039; }, [ 200, { &#039;Content-Type&#039; =&gt; &#039;text/plain&#039;, &#039;Content-Length&#039; =&gt; &#039;11&#039; }, [ &#039;Hello Again&#039; ]])
#
#  After each test, to remove all expectations:
#
#   @mock_server.clear
#
#  In teardown method:
#
#    @mock_server.stop

class MockServer

  def initialize(options={})
    host = options[:host] &#124;&#124; &#039;127.0.0.1&#039;
    port = options[:port] &#124;&#124; 4000
    @expectations = []
    @server = Thin::Server.new(host, port, self)
    @thread = Thread.new { @server.start }
  end

  def stop
    @server.stop!
    Thread.kill(@thread)
  end

  # env should be a hash mapping elements of a Rack env to expected values (see examples above);
  # note that an expected value can be a Proc which will be passed the value from the request
  # and executed - if the Proc returns true on execution, the expectation is met
  #
  # For example, to check that the querystring contains the value &#039;1234&#039;, env could be:
  #
  #   { &#039;QUERY_STRING&#039; =&gt; lambda { &#124;qs&#124; !((qs =~ /1234/).nil?) } }
  #
  # response should be a Rack-formatted response; i.e. [response_code, {&#039;header&#039; =&gt; &#039;value&#039;, ...}, response_body]
  #
  # options:
  #   :transient =&gt; false to prevent a response being removed after it has been served (default is true)
  def register(env, response, options={})
    transient = options[:transient]
    transient = true if transient.nil?

    @expectations &lt; &#039;text/plain&#039;}, &quot;Bad, bad, bad - couldn&#039;t map request to expectation&quot;]

    @expectations.each_with_index do &#124;expectation, index&#124;
      expectation_env, matched_response, transient = expectation
      matched = false

      expectation_env.each do &#124;env_key, value&#124;
        puts &quot;Trying to match #{env_key} =&gt; #{value} to request&quot;
	matched = true

        req_value = env[env_key]

	if value.is_a? Proc
          req_element_matches = value.call(req_value)
        else
          req_element_matches = (value == req_value)
        end

        unless req_element_matches
          puts &quot;  Value NOT matched: request value was #{env[env_key]} (needed #{value} to match)&quot;
          matched = false
          break
        end

      end

      if matched
        if transient
          @expectations.delete_at(index)
        end
        response = matched_response
        break
      end

    end

    response
  end

end&lt;/code&gt;</description>
		<content:encoded><![CDATA[<p>Bad, bad me. My code had an error in it. Fixed in this version:</p>
<p><code>require 'rubygems'<br />
require 'rack'<br />
require 'thin'</p>
<p># Mock server for testing bad or heavyweight server responses; runs on localhost:4000 by default<br />
#<br />
# Example of use<br />
#<br />
#  In setup method:<br />
#<br />
#    @mock_server = MockServer.new   # creating a new instance spawns a thread running the TCP server<br />
#    @mock_server.register( { 'REQUEST_METHOD' =&gt; 'GET' }, [ 200, { 'Content-Type' =&gt; 'text/plain', 'Content-Length' =&gt; '11' }, [ 'Hello World' ]])<br />
#    @mock_server.register( { 'REQUEST_METHOD' =&gt; 'GET' }, [ 200, { 'Content-Type' =&gt; 'text/plain', 'Content-Length' =&gt; '11' }, [ 'Hello Again' ]])<br />
#<br />
#  After each test, to remove all expectations:<br />
#<br />
#   @mock_server.clear<br />
#<br />
#  In teardown method:<br />
#<br />
#    @mock_server.stop</p>
<p>class MockServer</p>
<p>  def initialize(options={})<br />
    host = options[:host] || '127.0.0.1'<br />
    port = options[:port] || 4000<br />
    @expectations = []<br />
    @server = Thin::Server.new(host, port, self)<br />
    @thread = Thread.new { @server.start }<br />
  end</p>
<p>  def stop<br />
    @server.stop!<br />
    Thread.kill(@thread)<br />
  end</p>
<p>  # env should be a hash mapping elements of a Rack env to expected values (see examples above);<br />
  # note that an expected value can be a Proc which will be passed the value from the request<br />
  # and executed - if the Proc returns true on execution, the expectation is met<br />
  #<br />
  # For example, to check that the querystring contains the value '1234', env could be:<br />
  #<br />
  #   { 'QUERY_STRING' =&gt; lambda { |qs| !((qs =~ /1234/).nil?) } }<br />
  #<br />
  # response should be a Rack-formatted response; i.e. [response_code, {'header' =&gt; 'value', ...}, response_body]<br />
  #<br />
  # options:<br />
  #   :transient =&gt; false to prevent a response being removed after it has been served (default is true)<br />
  def register(env, response, options={})<br />
    transient = options[:transient]<br />
    transient = true if transient.nil?</p>
<p>    @expectations &lt; 'text/plain'}, "Bad, bad, bad - couldn't map request to expectation"]</p>
<p>    @expectations.each_with_index do |expectation, index|<br />
      expectation_env, matched_response, transient = expectation<br />
      matched = false</p>
<p>      expectation_env.each do |env_key, value|<br />
        puts "Trying to match #{env_key} =&gt; #{value} to request"<br />
	matched = true</p>
<p>        req_value = env[env_key]</p>
<p>	if value.is_a? Proc<br />
          req_element_matches = value.call(req_value)<br />
        else<br />
          req_element_matches = (value == req_value)<br />
        end</p>
<p>        unless req_element_matches<br />
          puts "  Value NOT matched: request value was #{env[env_key]} (needed #{value} to match)"<br />
          matched = false<br />
          break<br />
        end</p>
<p>      end</p>
<p>      if matched<br />
        if transient<br />
          @expectations.delete_at(index)<br />
        end<br />
        response = matched_response<br />
        break<br />
      end</p>
<p>    end</p>
<p>    response<br />
  end</p>
<p>end</code></p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Elliot Smith</title>
		<link>http://dynamicorange.com/2009/02/18/ruby-mock-web-server/#comment-4544</link>
		<dc:creator>Elliot Smith</dc:creator>
		<pubDate>Wed, 04 Mar 2009 20:07:07 +0000</pubDate>
		<guid isPermaLink="false">http://dynamicorange.com/?p=447#comment-4544</guid>
		<description>Tried  tags, but didn&#039;t take</description>
		<content:encoded><![CDATA[<p>Tried  tags, but didn&#8217;t take</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Elliot Smith</title>
		<link>http://dynamicorange.com/2009/02/18/ruby-mock-web-server/#comment-4543</link>
		<dc:creator>Elliot Smith</dc:creator>
		<pubDate>Wed, 04 Mar 2009 20:06:46 +0000</pubDate>
		<guid isPermaLink="false">http://dynamicorange.com/?p=447#comment-4543</guid>
		<description>Small rewrite which adds:

* Ability to specify an expectation as not being transient - i.e. not deleted after its response is served
* Run in a thread after instantiation (makes tests simpler to write)
* Facility to pass a lambda in as the expectation, to execute the value from the request against - allows you to do arbitrary matching of request elements against expectations


require &#039;rubygems&#039;
require &#039;rack&#039;
require &#039;thin&#039;

# Mock server for testing bad or heavyweight server responses; runs on localhost:4000 by default
#
# Example of use
#
#  In setup method:
#
#    @mock_server = MockServer.new   # creating a new instance spawns a thread running the TCP server
#    @mock_server.register( { &#039;REQUEST_METHOD&#039; =&gt; &#039;GET&#039; }, [ 200, { &#039;Content-Type&#039; =&gt; &#039;text/plain&#039;, &#039;Content-Length&#039; =&gt; &#039;11&#039; }, [ &#039;Hello World&#039; ]])
#    @mock_server.register( { &#039;REQUEST_METHOD&#039; =&gt; &#039;GET&#039; }, [ 200, { &#039;Content-Type&#039; =&gt; &#039;text/plain&#039;, &#039;Content-Length&#039; =&gt; &#039;11&#039; }, [ &#039;Hello Again&#039; ]])
#
#  After each test, to remove all expectations:
#
#   @mock_server.clear
#
#  In teardown method:
#
#    @mock_server.stop

class MockServer

  def initialize(options={})
    host = options[:host] &#124;&#124; &#039;127.0.0.1&#039;
    port = options[:port] &#124;&#124; 4000
    @expectations = []
    @server = Thin::Server.new(host, port, self)
    @thread = Thread.new { @server.start }
  end

  def stop
    @server.stop!
    Thread.kill(@thread)
  end

  # env should be a hash mapping elements of a Rack env to expected values (see examples above);
  # note that an expected value can be a Proc which will be passed the value from the request
  # and executed - if the Proc returns true on execution, the expectation is met
  #
  # For example, to check that the querystring contains the value &#039;1234&#039;, env could be:
  #
  #   { &#039;QUERY_STRING&#039; =&gt; lambda { &#124;qs&#124; !((qs =~ /1234/).nil?) } }
  #
  # response should be a Rack-formatted response; i.e. [response_code, {&#039;header&#039; =&gt; &#039;value&#039;, ...}, response_body]
  #
  # options:
  #   :transient =&gt; false to prevent a response being removed after it has been served (default is true)
  def register(env, response, options={})
    transient = options[:transient]
    transient = true if transient.nil?

    @expectations &lt; &#039;text/plain&#039;}, &quot;Bad, bad, bad - couldn&#039;t map request to expectation&quot;]

    @expectations.each_with_index do &#124;expectation, index&#124;
      expectation_env, response, transient = expectation
      matched = false

      expectation_env.each do &#124;env_key, value&#124;
        puts &quot;Trying to match #{env_key} =&gt; #{value} to request&quot;
	matched = true

        req_value = env[env_key]

	if value.is_a? Proc
          req_element_matches = value.call(req_value)
        else
          req_element_matches = (value == req_value)
        end

        unless req_element_matches
          puts &quot;  Value NOT matched: request value was #{env[env_key]} (needed #{value} to match)&quot;
          matched = false
          break
        end

      end

      if matched and transient
        @expectations.delete_at(index)
        break
      end
    end

    response
  end

end</description>
		<content:encoded><![CDATA[<p>Small rewrite which adds:</p>
<p>* Ability to specify an expectation as not being transient &#8211; i.e. not deleted after its response is served<br />
* Run in a thread after instantiation (makes tests simpler to write)<br />
* Facility to pass a lambda in as the expectation, to execute the value from the request against &#8211; allows you to do arbitrary matching of request elements against expectations</p>
<p>require &#8216;rubygems&#8217;<br />
require &#8216;rack&#8217;<br />
require &#8216;thin&#8217;</p>
<p># Mock server for testing bad or heavyweight server responses; runs on localhost:4000 by default<br />
#<br />
# Example of use<br />
#<br />
#  In setup method:<br />
#<br />
#    @mock_server = MockServer.new   # creating a new instance spawns a thread running the TCP server<br />
#    @mock_server.register( { &#8216;REQUEST_METHOD&#8217; =&gt; &#8216;GET&#8217; }, [ 200, { 'Content-Type' =&gt; 'text/plain', 'Content-Length' =&gt; '11' }, [ 'Hello World' ]])<br />
#    @mock_server.register( { &#8216;REQUEST_METHOD&#8217; =&gt; &#8216;GET&#8217; }, [ 200, { 'Content-Type' =&gt; 'text/plain', 'Content-Length' =&gt; '11' }, [ 'Hello Again' ]])<br />
#<br />
#  After each test, to remove all expectations:<br />
#<br />
#   @mock_server.clear<br />
#<br />
#  In teardown method:<br />
#<br />
#    @mock_server.stop</p>
<p>class MockServer</p>
<p>  def initialize(options={})<br />
    host = options[:host] || &#8217;127.0.0.1&#8242;<br />
    port = options[:port] || 4000<br />
    @expectations = []<br />
    @server = Thin::Server.new(host, port, self)<br />
    @thread = Thread.new { @server.start }<br />
  end</p>
<p>  def stop<br />
    @server.stop!<br />
    Thread.kill(@thread)<br />
  end</p>
<p>  # env should be a hash mapping elements of a Rack env to expected values (see examples above);<br />
  # note that an expected value can be a Proc which will be passed the value from the request<br />
  # and executed &#8211; if the Proc returns true on execution, the expectation is met<br />
  #<br />
  # For example, to check that the querystring contains the value &#8217;1234&#8242;, env could be:<br />
  #<br />
  #   { &#8216;QUERY_STRING&#8217; =&gt; lambda { |qs| !((qs =~ /1234/).nil?) } }<br />
  #<br />
  # response should be a Rack-formatted response; i.e. [response_code, {'header' =&gt; 'value', ...}, response_body]<br />
  #<br />
  # options:<br />
  #   :transient =&gt; false to prevent a response being removed after it has been served (default is true)<br />
  def register(env, response, options={})<br />
    transient = options[:transient]<br />
    transient = true if transient.nil?</p>
<p>    @expectations &lt; &#8216;text/plain&#8217;}, &#8220;Bad, bad, bad &#8211; couldn&#8217;t map request to expectation&#8221;]</p>
<p>    @expectations.each_with_index do |expectation, index|<br />
      expectation_env, response, transient = expectation<br />
      matched = false</p>
<p>      expectation_env.each do |env_key, value|<br />
        puts &#8220;Trying to match #{env_key} =&gt; #{value} to request&#8221;<br />
	matched = true</p>
<p>        req_value = env[env_key]</p>
<p>	if value.is_a? Proc<br />
          req_element_matches = value.call(req_value)<br />
        else<br />
          req_element_matches = (value == req_value)<br />
        end</p>
<p>        unless req_element_matches<br />
          puts &#8221;  Value NOT matched: request value was #{env[env_key]} (needed #{value} to match)&#8221;<br />
          matched = false<br />
          break<br />
        end</p>
<p>      end</p>
<p>      if matched and transient<br />
        @expectations.delete_at(index)<br />
        break<br />
      end<br />
    end</p>
<p>    response<br />
  end</p>
<p>end</p>
]]></content:encoded>
	</item>
</channel>
</rss>

