Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

In Rails controller tests, Is there a way to simulate a specific remote IP?

Some functionality in my app works differently depending on the client's IP address. Is there a way to test that in Rails functional tests? I'm using Test::Unit and Shoulda.

like image 871
Ethan Avatar asked Jan 19 '10 03:01

Ethan


3 Answers

You can do this easily without stubbing, by changing the REMOTE_ADDR environment variable before your controller call. Here's a fictional controller that redirects the user to the home path if their ip address is 1.2.3.4:

def index
  if request.remote_ip == '1.2.3.4'
    redirect_to root_path
    return
  end

  @articles = Article.all
end

Here's how you can test that it works:

def test_should_reject_ip_1_2_3_4
  @request.env['REMOTE_ADDR'] = '1.2.3.4'
  get :index
  assert_redirected_to root_path
end

You're setting the remote ip in advance of the controller call, so you're able to fake that data without any special plugins or gems. And here's the shoulda version, for ItemsController:

context "with ip 1.2.3.4" do
  setup do
    @request.env['REMOTE_ADDR'] = '1.2.3.4'
    get :index
  end

  should_not_assign_to :items
  should_redirect_to("home"){home_path}
  should_not_set_the_flash
end
like image 164
Jaime Bellmyer Avatar answered Oct 16 '22 17:10

Jaime Bellmyer


The receiving controller needs a method for detecting the IP address (or receiving it as a parameter), and you need a way to inject a specific IP address for your test, or just specifying the test IP address as a parameter to the method.

If that's not easy considering whatever your app does, what you could do is make the "custom functionality" apply to another computer on your home network, if you have one, and test the app that way. That doesn't really solve the "solve it through a unit test" answer though.

Can I ask why your app would perform a specific action depending on the IP address? Perhaps there's another way.

like image 33
jefflunt Avatar answered Oct 16 '22 19:10

jefflunt


You should be able to accomplish this by stubbing out the requests and returning a mock object that has request.remote_ip equal to the desired IP address.

I'd look at FakeWeb for help on this. It lets you easily set up the expected requests/responses. It might also be instructive to look at how Rails itself does these kinds of tests.

like image 24
zetetic Avatar answered Oct 16 '22 18:10

zetetic