views:

38

answers:

2

I'm looking for the best way to write unit test for code that POSTs to an external web service. The body of the POST request is an XML document which describes the actions and data for the web service to perform.

Now, I've wrapped the webservice in its own class (similar to ActiveResource), and I can't see any way to test the exact XML being generated by the class without breaking encapsulation by exposing some of the internal XML generation as public methods on the class. This seems to be a code smell - from the point-of-view of the users of the class, they should not know, nor care, how the class actually implements the web service call, be it with XML, JSON or carrier pigeons.

For an example of the class:

class Resource
  def new
    #initialize the class
  end

  def save!
    Http.post("http://webservice.com", self.to_xml)
  end

  private
  def to_xml
    # returns an XML representation of self
  end
end

I want to be able to test the XML generated to ensure it conforms to what the specs for the web service are expecting. So can I best do this, without making to_xml a public method?

+1  A: 

Instead of calling a private method, you can send a message:

myobject.send(:method_name, args)

This should avoid any problems accessing the private method. Perhaps more elegantly, if you're using rSpec you can do this:

before(:each) do
  MyClass.send(:public, *MyClass.protected_instance_methods)  
end

and then in your tests you can call the method normally.

Mark Thomas
You can use send to call private methods in Ruby 1.8, but not 1.9. It's still a hack though - I want to test against interfaces (the Ruby one, and the web service one), not the internal implementation of them - if I change how I generate my XML inside the class, I shouldn't have to change my tests.
Jason Langenauer
A: 

Check out either Netrecorder(http://github.com/chrisyoung/netrecorder) or Fakeweb(http://github.com/chrisk/fakeweb).

Nick Hammond