Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to test a ruby application which uses mechanize

I wrote a small program that uses Mechanize to traverse a site.

I want to write tests for it, but don't want it to actually go log onto the site every time I run the tests. I would like to mock the internet, so that when it goes to some site, it simply returns the stored results.

Here is a small example, pretend my code's purpose was to pull links off of the google homepage, so I write a test to ensure the first link my code finds has the text "Images". I might write something like this:

require 'rubygems'
require 'mechanize'
require 'test/unit'

def my_code_to_find_links
  google = WWW::Mechanize.new.get('http://www.google.com')
  # ...
  # some code to figure out which links it wants
  # ...
  google.links
end

class TestGoogle < Test::Unit::TestCase
  def test_first_link_is_images
    assert_equal 'Images' , my_code_to_find_links.first.text
  end
end

How do I mock google.com so that I can test my_code_to_find_links without all the overhead of actually accessing the internet?

thanks -Josh

like image 516
Joshua Cheek Avatar asked Jan 28 '10 02:01

Joshua Cheek


1 Answers

Use Fakeweb to stub out the internet responses.

For the Google example, first go to the website and save the html of the page you desire. In this case, let's assume you saved www.google.com via your browser or curl. Add the Fakeweb gem to your test.rb file

Then your code is

stream = File.read("saved_google_page.html")
FakeWeb.register_uri(:get, 
    "http://www.google.com", 
    :body => stream, 
    :content_type => "text/html")

When you do your standard Mechanize call of

agent = Mechanize.New
page = agent.get("http://www.google.com/")

Fakeweb will return the page you saved with the content_type headers set in a way that Mechanize will think it accessed the internet successfully. Make sure that content_type header is set since otherwise Mechanize treats the response as Mechanize::File instead of Mechanize::Page. You can test that it's fully working by running tests on your machine with the network connection unplugged.

p.s. I'm answering this 6 months after the question was asked since this is the top result in Google but it's unanswered. I just spent 30 minutes figuring this out myself and thought I'd share the solution.

like image 105
rhh Avatar answered Oct 19 '22 21:10

rhh