Nate
Nate

Reputation: 4749

How to fake a web service with ruby and MiniTest

I'm writing a Rails app to send text messages using the Twilio API:

http://www.twilio.com/docs/api/rest/sending-sms

and to this end, I do:

client = Twilio::REST::Client.new account_sid, auth_token
client.account.sms.messages.create({
    # stuff ...
}) 

That's all good and nice -- however, I don't want my tests to send a bunch of text messages because that would be stupid. So, I'd like to override Twilio::REST::Client.new to give me an object that'll let me call acccount.sms.messages.create in my tests without undue fuss.

I have a solution that works, but feels ugly:

def mock_twilio_service(stub_client)
  Twilio::REST::Client.stub :new, stub_client do
    yield
  end
end

class Recordy
  attr_accessor :calls
  def initialize
    @calls = []
  end

  def method_missing(method, *args)
    ret = self.class.new
    @calls << {
      method: method,
      args: args,
      block_given: block_given?,
      ret: ret
    }
    yield if block_given?
    ret
  end
end

and then in my test:

test "send a text" do
  cli = Recordy.new
  mock_twilio_service cli do
    # ... stuff
  end
end

I feel like I'm missing something Super Obvious, but I'm not sure. Am I? Or am I totally barking up the wrong tree? (Yes, I've looked at How do I mock a Class with Ruby? but I don't think it's quite the same...?)

Upvotes: 2

Views: 2104

Answers (2)

Kristiina
Kristiina

Reputation: 533

Another idea would be to use WebMock. As your client is making requests to Twilio. You can just stub out the requests. Within the stub you can also define what is returned from the requests and with which parameters it can be called.

And when you set

   WebMock.disable_net_connect!

it is sure that no real requests can be made from the test.

This way you don't change any behavior of your test and will not rely on an external API for your tests to pass.

Upvotes: 1

Devin Rader
Devin Rader

Reputation: 10366

Twilio evangelist here.

We wrote Test Credentials exactly for this scenario. Test Credentials are a special set of credentials (AccountSid and AuthToken) that you can use when you make requests to the Twilio REST API that tell it to basically just go through the motions of making a phone call or sending a text message, but not actually do it (or charge you for it).

You can also use a special set of phone numbers to get Twilio to return specific success or error conditions.

You can find your test credentials in your Twilio dashboard.

Hope that helps.

Upvotes: 2

Related Questions