0
class SessionsController < ApplicationController::Base  
  def create
      result = verify_sms_code(params[:session][:phone], params[:session][:code]
       if result['code'] == 200
         render json: {code: 200, msg: 'success'}
       else
         render json: {code: 404, msg: 'failed'}
       end
    end
end

The verify_sms_code method invokes third party API from network, the API returns JSON result for validation short message.

How can I test create action? Thanks

3 Answers 3

1

You can stub method making external api call i.e verify_sms_code in your case. You can write something like

SessionsController.any_instance.stub(:verify_sms_code).and_return({code: 200, data: ''})

When you write above code whenever you use verify_sms_code inside SessionsController it will return the hash that you provide i.e {code: 200, data: ''}

If you are using rspec 3 and above, you can mock verify_sms_code as following inside controller.

allow(controller).to receive(:verify_sms_code).and_return({code: 200, data: ''})

Reference link:

https://www.relishapp.com/rspec/rspec-mocks/v/2-6/docs/method-stubs/stub-on-any-instance-of-a-class

http://rspec.info/documentation/3.4/rspec-mocks/

There are also other ways to mock. Check below link

https://robots.thoughtbot.com/how-to-stub-external-services-in-tests

Example:

it "does something" do   
  SessionsController.any_instance.stub(:verify_sms_code).and_return({code: 200, data: "success data"})
end

it "does other thing" do 
   SessionsController.any_instance.stub(:verify_sms_code).and_return({code: 404, data: "error data"})
end
Sign up to request clarification or add additional context in comments.

4 Comments

but how to change the return value? For some reason, I want to return {code:404} in other examples , but SessionsController.any_instance.stub(:verify_sms_code).and_return({code: 200, data: ''}) returns {code: 200, data:""} in all examples
@Ryman1981 updated my answer with example. You have to stub it on per example bases if you need to return different response inside different examples
As of RSpec 3.3 , any_instance is deprecated and not recommended. I use the allow(controller).to receive(:verify_sms_code).and_return({code: 200, data: 'success data'}, {code: 404, data: 'error data'}) but it only returns first response
Thanks for the info. I will update my answer with the new method for rspec 3.3
0

I use the VCR gem for testing actions that make API calls. It lets you record API responses to use them in tests.

https://github.com/vcr/vcr

Comments

0

I use webmock and like it quite a lot. I get a lot of control over headers, params, return content, return headers, return status, etc. But, not a lot of overhead.

I put all of my stub_requests into a shared set of files then include them en masse via rails_helper.rb. That way, I can reuse my stub_requests throughout my test suite.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.