In a project that I’m currently working on, we’re handling recurring
payments for subscribers. I’ve decided to play with a different payment
service API on this project
(TrustCommerce), 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
CISP-compliant.
I came across the TrustCommerce
Subscription
plugin for Rails, which does just everything that I need to do in this
first product release… as well as things that aren’t requirements just
yet.
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… test
accounts don’t give you the ability to test the
Citadel features of
TrustCommerce. It’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.
Suppose that you were going to perform something like this in an AR
callback.
class BillingDetail < 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 => self.credit_card_number,
:exp => '0412',
:name => self.customer_name,
:amount => 1,
:cycle => '1y',
:demo => 'y'
)
if response['status'] == 'approved'
self.billing_id = response['billingid']
else
# handle failure
end
end
end
Enter Mock Objects
Since I am unable to succesfully use the
TrustCommerceGateway::Subscription.create method until I get our real
account, I needed a simple way to emulate the interaction with the web
service.
This can be done by using a Mock object, which RSpec provides for you.
TrustCommerceGateway::Subscription.stub!(:create).and_return( {expected response} )
Let’s look at the following spec file (much of it removed to protect the
innocent).
module ValidBillingDetail
def valid_attributes
{ # a hash of valid key/values for this model }
end
def approved_trust_commerce_subscription
{ 'status' => 'approved', 'billingid' => '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
You’ll notice a few things. First, you’ll see that I’ve stubbed the
create method and when it is called in the method in my model, it’ll
return the hash that I’ve specified.
TrustCommerceGateway::Subscription.stub!(:create).and_return( approved_trust_commerce_subscription )
In the spec, you will see that I am checking that that the
.billing_id.should_not_be nil. If you look back in the method in the
model above, you will notice that an approved subscription returns a
billing_id, which is set when the transaction is successful.
This is working out great for me and because the documentation is fairly
easy to follow, I’m going to be able to mock much of the behavior that
I’ll be using in the application, without needing to even connect to
their API.
If you’re using RSpec, I highly encourage you to read more about mocks
objects.