<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet href="/stylesheets/rss.css" type="text/css"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/">
  <channel>
    <title>Robby on Rails: Be Careful that you don't Stub your Big Toe</title>
    <link>http://www.robbyonrails.com/articles/2007/02/13/be-careful-that-you-dont-stub-your-big-toe</link>
    <language>en-us</language>
    <ttl>40</ttl>
    <description>thoughts.sort_by{|t| t[:topic]}.collect </description>
    <item>
      <title>Be Careful that you don't Stub your Big Toe</title>
      <description>&lt;p&gt;In a project that I&amp;#8217;m currently working on, we&amp;#8217;re handling recurring payments for subscribers. I&amp;#8217;ve decided to play with a different payment service &lt;span class="caps"&gt;API&lt;/span&gt; on this project (&lt;a href="http://www.trustcommerce.com/"&gt;TrustCommerce&lt;/a&gt;), which supposedly has one of the easier systems to handle recurring payments as well as one-time charges to the same credit cards. They store all the credit card data so that our delivered product to the client is &lt;a href="http://usa.visa.com/merchants/risk_management/cisp.html"&gt;&lt;span class="caps"&gt;CISP&lt;/span&gt;-compliant&lt;/a&gt;.&lt;/p&gt;


	&lt;p&gt;I came across the &lt;a href="http://www.agilewebdevelopment.com/plugins/trustcommerce_subscription"&gt;TrustCommerce Subscription&lt;/a&gt; plugin for Rails, which does just everything that I need to do in this first product release&amp;#8230; as well as things that aren&amp;#8217;t requirements just yet.&lt;/p&gt;


	&lt;p&gt;Well, I got my test account from TrustCommerce and was working on some RSpecs to test my new subscription and noticed that it was failing. After some snooping around the error responses, I realized that&amp;#8230; test accounts don&amp;#8217;t give you the ability to test the &lt;a href="http://www.trustcommerce.com/citadel.php"&gt;Citadel&lt;/a&gt; features of TrustCommerce. It&amp;#8217;ll be another week or so before finish getting our account setup, so what am I to do? I really want to finish writing these specs and move on to the other portions that are dependent upon this working.&lt;/p&gt;


	&lt;p&gt;Suppose that you were going to perform something like this in an AR callback.&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;
class BillingDetail &amp;lt; ActiveRecord::Base

  # validations    

  before_create :store_credit_card_data_with_trust_commerce

  private 

    def store_credit_card_data_with_trust_commerce
      # some of this is still test data... prettyu much copied from the README
      # TODO: refactor... but keep me out of controllers!
      response = TrustCommerceGateway::Subscription.create(
          :cc =&amp;gt;  self.credit_card_number, 
          :exp =&amp;gt; '0412', 
          :name =&amp;gt; self.customer_name,
          :amount =&amp;gt; 1,
          :cycle =&amp;gt; '1y',
          :demo =&amp;gt; 'y'
        )

      if response['status'] == 'approved'
          self.billing_id = response['billingid']
        else
        # handle failure
        end
    end
end
&lt;/code&gt;&lt;/pre&gt;

	&lt;h2&gt;Enter Mock Objects&lt;/h2&gt;


	&lt;p&gt;Since I am unable to succesfully use the &lt;code&gt;TrustCommerceGateway::Subscription.create&lt;/code&gt; method until I get our real account, I needed a simple way to emulate the interaction with the web service.&lt;/p&gt;


	&lt;p&gt;This can be done by using a Mock object, which RSpec provides for you.&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;
TrustCommerceGateway::Subscription.stub!(:create).and_return( {expected response} )
&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;Let&amp;#8217;s look at the following spec file (much of it removed to protect the innocent).&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;
module ValidBillingDetail
  def valid_attributes
    { # a hash of valid key/values for this model }
  end

  def approved_trust_commerce_subscription
    { 'status' =&amp;gt; 'approved', 'billingid' =&amp;gt; '1093423' } 
  end
end

context "A new billing detail" do
  include ValidBillingDetail

  setup do
    TrustCommerceGateway::Subscription.stub!(:create).and_return( approved_trust_commerce_subscription )
  end

  # bunch of other specs

  specify "should store new billing info with 3rd party API and store the billingid" do
    @billing_detail = BillingDetail.create( valid_attributes )
    @billing_detail.billing_id.should_not_be nil
  end
end  
&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;You&amp;#8217;ll notice a few things. First, you&amp;#8217;ll see that I&amp;#8217;ve stubbed the &lt;code&gt;create&lt;/code&gt; method and when it is called in the method in my model, it&amp;#8217;ll return the hash that I&amp;#8217;ve specified.&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;TrustCommerceGateway::Subscription.stub!(:create).and_return( approved_trust_commerce_subscription )&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;In the spec, you will see that I am checking that that the &lt;code&gt;.billing_id.should_not_be nil&lt;/code&gt;. If you look back in the method in the model above, you will notice that an approved subscription returns a &lt;code&gt;billing_id&lt;/code&gt;, which is set when the transaction is successful.&lt;/p&gt;


	&lt;p&gt;This is working out great for me and because the documentation is fairly easy to follow, I&amp;#8217;m going to be able to mock much of the behavior that I&amp;#8217;ll be using in the application, without needing to even connect to their &lt;span class="caps"&gt;API&lt;/span&gt;.&lt;/p&gt;


	&lt;p&gt;If you&amp;#8217;re using RSpec, I highly encourage you to read more about &lt;a href="http://rspec.rubyforge.org/documentation/mocks/mocks.html"&gt;mocks objects&lt;/a&gt;.&lt;/p&gt;
</description>
      <pubDate>Tue, 13 Feb 2007 01:09:00 -0600</pubDate>
      <guid isPermaLink="false">urn:uuid:6e9733fb-1d6b-42a8-a0ad-29948aacd45c</guid>
      <author>Robby Russell</author>
      <link>http://www.robbyonrails.com/articles/2007/02/13/be-careful-that-you-dont-stub-your-big-toe</link>
      <category>Ruby on Rails</category>
      <category>Ruby</category>
      <category>Programming</category>
      <category>rspec</category>
      <category>bdd</category>
      <category>mocks</category>
      <category>stubs</category>
      <category>trustcommerce</category>
      <category>plugins</category>
      <category>testing</category>
    </item>
  </channel>
</rss>
