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

4

15

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.

Nordau answered 19/1, 2010 at 3:47 Comment(0)
N
32

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
Neuralgia answered 19/1, 2010 at 5:11 Comment(0)
V
1

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.

Vitavitaceous answered 19/1, 2010 at 4:26 Comment(1)
Why detecting IP: the app shows different UI elements depending on whether user in inside or outside our local network.Nordau
L
1

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.

Lore answered 19/1, 2010 at 4:32 Comment(0)
F
0

Using gem "mocha" you can do:

test "should something" do
  request.expects(:remote_ip).returns("189.81.139.183")
  ...
end
Florio answered 5/7, 2012 at 13:47 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.