Testing Ruby on Rails Models with no Database Mapping

Dec 21, 2011 Published by Tony Primerano

I recently built a rails application that only talked to a web service. This called for some slight changes in the way I needed to run my unit tests.

For my tests I took some real responses from the web service I was consuming and saved them into xml file that my unit tests would then open an process. This allowed me to get complete code coverage on my models which came in handy as I moved from REXML to Hpricot to libxml.

Here is the approach I took.

I created models for pieces of the xml responses. For example. When I was retrieving a list of posts there was a rating on each post so I created a rating class (app/models/rating.rb). Note it does NOT inherit from ActiveRecord since there is no database to map to.

class Rating
    def initialize  (rating)
      @score = rating.find("score")[0].child.content
      @sample = rating.find("sample")[0].child.content
      @percent = rating.find("percent")[0].child.content

    def get_score
      return @score

    def get_sample
      return @sample

    def get_percent
      return @percent

I then had an article class that used the rating class among others.

So now to test this class.

1st I saved several sample XML responses to test/sample_responses/

Then I added a helper to test/test_helper.rb

  # Add more helper methods to be used by all tests here...
  def get__data(fn)
    IO.read RAILS_ROOT + "/test/sample_responses/#{fn}"

I then used this helper in my test/unit/boards_test.rb file

      r = Response.new(get_sample_data("threaded_list.xml"))
      assert_equal "2", r.get_articles()[0].get_rating().get_score
      assert_equal "5", r.get_articles()[0].get_rating().get_sample
      assert_equal "0.4", r.get_articles()[0].get_rating().get_percent

response.rb parses the passed xml and instantiates the article class among others. Normally it is getting its data from an http request but to allow for thougough and consistent testing of my models I used files from disk.