4
config.before(:each) do
  stub_request(:post, "https://api.3rdpartysmsprovider.com/send.php?body=This%20is%20a%20test%20message&destination=60123456789&dlr='1'&output=json&password=0000000&reference=#{@text.sms_uid}&sender=silver&username=0000000").
    to_return(:status => 200, :body => "01", :headers => {})
end

I am currently writing specs for a service class that sends an SMS and creates a log of it in our database. I'm trying to stub this request, however @text.sms_uid is a SecureRandom.urlsafe_base64 random code. Also I'm stubbing in config.before(:each).

Because of that, I can't specify the sms_uid in stub_request as the random sms_uid is generated after the stub is called. This causes the test to fail every time. Is there a way I can stub the request after it generates the code (in other words, after it goes through the specific method) or is there a way to stub all requests going through the domain "https://api.silverstreet.com"?

Dave Schweisguth
  • 36,475
  • 10
  • 98
  • 121
Tharan Raj
  • 43
  • 1
  • 4

1 Answers1

2

I see two options:

  • Stub SecureRandom.urlsafe_base64 to return a known string and use that known string when you stub_request:

    config.before(:each) do
      known_string = "known-string"
      allow(SecureRandom).to receive(:known_string) { known_string }
      stub_request(:post, "https://api.3rdpartysmsprovider.com/send.php?body=This%20is%20a%20test%20message&destination=60123456789&dlr='1'&output=json&password=0000000&reference=#{known_string}&sender=silver&username=0000000").
        to_return(status: 200, body: "01", headers: {})
    end
    

    If SecureRandom.urlsafe_base64 is used in other places in your application, you'll need to stub it only in the specs where this request is generated.

  • Yes, you can stub any POST to that hostname

    stub_request(:post, "api.3rdpartysmsprovider.com").
      to_return(status: 200, body: "01", headers: {})
    

    or even any request of any kind to that hostname

    stub_request(:any, "api.3rdpartysmsprovider.com").
      to_return(status: 200, body: "01", headers: {})
    

    and webmock has a very large number of other ways to match requests.

Dave Schweisguth
  • 36,475
  • 10
  • 98
  • 121
  • 1
    Hey thanks for the answer! I had no idea I could stub SecureRandom. Anyway, I managed to solve it using regex `stub_request(:post, %r{https://api.3rdpartysmsprovider.com}). to_return(:status => 200, :body => "01", :headers => {})` which is basically `stub_request(:post, "api.3rdpartysmsprovider.com"). to_return(status: 200, body: "01", headers: {})` except for some reason stubbing it as a string didn't work for me – Tharan Raj Jun 04 '16 at 20:11