Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to setup a Rails integration test for XML methods?

Given a controller method like:

def show
  @model = Model.find(params[:id])

  respond_to do |format|
    format.html # show.html.erb
    format.xml  { render :xml => model }
  end
end

What's the best way to write an integration test that asserts that the return has the expected XML?

like image 712
Patrick Ritchie Avatar asked Sep 12 '08 18:09

Patrick Ritchie


People also ask

How do you run a test in rails?

We can run all of our tests at once by using the bin/rails test command. Or we can run a single test file by passing the bin/rails test command the filename containing the test cases. This will run all test methods from the test case.

How do you test a method in Ruby?

Most methods can be tested by saying, “When I pass in argument X, I expect return value Y.” This one isn't so straightforward though. This is more like “When the user sees output X and then enters value V, expect subsequent output O.” Instead of accepting arguments, this method gets its value from user input.

How do you run a Minitest?

Setting Up Minitest. To run a Minitest test, the only setup you really need is to require the autorun file at the beginning of a test file: require 'minitest/autorun' . This is good if you'd like to keep the code small. A better way to get started with Minitest is to have Bundler create a template project for you.

What is rails integration test?

While unit tests make sure that individual parts of your application work, integration tests are used to test that different parts of your application work together.


2 Answers

A combination of using the format and assert_select in an integration test works great:

class ProductsTest < ActionController::IntegrationTest
  def test_contents_of_xml
    get '/index/1.xml'
    assert_select 'product name', /widget/
  end
end

For more details check out assert_select in the Rails docs.

like image 131
ntalbott Avatar answered Nov 15 '22 23:11

ntalbott


The answer from ntalbott shows a get action. The post action is a little trickier; if you want to send the new object as an XML message, and have the XML attributes show up in the params hash in the controller, you have to get the headers right. Here's an example (Rails 2.3.x):

class TruckTest < ActionController::IntegrationTest
  def test_new_truck
    paint_color = 'blue'
    fuzzy_dice_count = 2
    truck = Truck.new({:paint_color => paint_color, :fuzzy_dice_count => fuzzy_dice_count})
    @headers ||= {}
    @headers['HTTP_ACCEPT'] = @headers['CONTENT_TYPE'] = 'application/xml'
    post '/trucks.xml', truck.to_xml, @headers
    #puts @response.body
    assert_select 'truck>paint_color', paint_color
    assert_select 'truck>fuzzy_dice_count', fuzzy_dice_count.to_s
  end
end

You can see here that the 2nd argument to post doesn't have to be a parameters hash; it can be a string (containing XML), if the headers are right. The 3rd argument, @headers, is the part that took me a lot of research to figure out.

(Note also the use of to_s when comparing an integer value in assert_select.)

like image 27
bjnord Avatar answered Nov 15 '22 23:11

bjnord