Sample stubs break if order of params changes #69

nickhammond opened this Issue Dec 17, 2010 · 6 comments

2 participants


If you use the sample stubs that webmock outputs when a request hasn't been mocked yet such as:

You can stub this request with the following snippet:

 stub_request(:post, "").with(:body => "<?xml version=\"1.0\" ?><first></first><second></second>")

If the order of those changes then the test will break which seems to be the case frequently when using XMLRPC. My test will run fine for a few times and then it will start failing. If I paste in the new sample stub then it passes again. This is without modification to the actual method that is calling it.

It's probably because it's seeing the body as a string and trying to match it exactly. Would it be possible to look at the Content-Type and if it's set as text/xml to handle it properly.


In my full call I have the Content-Type set to text/xml in the headers hash.


Can you re-open this, I accidently hit "Comment & close" instead of just comment.


Of course, it would be possible to generate a snippet with body declared as a ruby hash instead of raw xml string.
The problem is that sometimes the order matters. I.e often order of xml elements is important in SOAP requests.
Possibly some configuration print_stub_snippets_with_xml_body_as_hash in webmock ? ;)
Not sure what's the best way to handle it yet.


hmm, well the annoying part(not webmock's fault) is xmlrpc just puts the params in any order it feels like which is only a problem because it's part of an array.

I took the XML and converted it into a hash but it's basically having problems because the index of certain elements doesn't match up I'm assuming.

Here's an example of the xml I'm dealing with(converted with XmlSimple.xml_in(xml_string):

{"methodName"=>["ContactService.add"], "params"=>[{"param"=>[{"value"=>[{"string"=>["f"]}]}, {"value"=>[{"struct"=>[{"member"=>[{"name"=>["ContactNotes"], "value"=>[{"string"=>["Some comments"]}]}, {"name"=>["_Iagree"], "value"=>[{"boolean"=>["1"]}]}, {"name"=>["FirstName"], "value"=>[{"string"=>["Jack"]}]}, {"name"=>["_Username"], "value"=>[{"string"=>[""]}]}, {"name"=>["LastName"], "value"=>[{"string"=>["Smith"]}]}, {"name"=>["_Password"], "value"=>[{"string"=>["password"]}]}, {"name"=>["Company"], "value"=>[{"string"=>["Example Group"]}]}, {"name"=>["_business"], "value"=>[{"string"=>["Entertainment"]}]}, {"name"=>["Email"], "value"=>[{"string"=>[""]}]}, {"name"=>["_ReferredBy"], "value"=>[{"string"=>["An affiliate"]}]}, {"name"=>["Phone1"], "value"=>[{"string"=>["6025551234"]}]}, {"name"=>["Phone5"], "value"=>[{"string"=>["16025551234"]}]}]}]}]}]}]}

Am I going about this wrong? What would you suggest?


Looks like the order of 'member' elements is not the same in every request you make
and webmock does care about the order.

Using a hash instead of raw xml also won't help i.e
stub_request(:post, "").with(:body => Crack::XML.parse(xml) )
since the order of elements in generated 'member' array will be different.

The only thing I can suggest is to write a custom block to match the request body i.e.

stub_request(:post, "").with { |request| your_custom_matching_method_returning_true_or_false(request.body)}

This method can for example parse xml to ruby hash and then do deep sorting of all arrays in a hash before comparing hashes.


Yeah, thanks for confirming it. Just wanted to make sure I wasn't going crazy from dealing with it for a while.

This issue was closed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment