<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<meta content="text/html;charset=ISO-8859-1" http-equiv="Content-Type">
</head>
<body bgcolor="#ffffff" text="#000000">
James,<br>
<br>
the gem is converting your hash to an array of arrays when it builds
the mock expectation. This is really an artifact of Ruby's hash/array
handling - the code in the gem looks perfectly reasonable, it just has
this side-effect.<br>
<br>
If you check out <tt>$GEM_DIR/rspec-0.7.5.1/lib/spec/mocks/message_expectation.rb</tt>
you will see that <tt>#with()</tt> passes your hash to a new instance
of <i>ArgumentExpectation,</i> which is defined in <tt>$GEM_DIR/rspec-0.7.5.1/lib/spec/mocks/argument_expectation.rb</tt>
. There you will see that a hash is a <i>LiteralArgConstraint</i>
(as opposed to <font color="#3366ff">:anything,</font> <font
color="#3366ff">:numeric</font>, and the other parameters that <tt>#with()</tt>
accepts). The interesting code is around line 89 in <tt>#process_arg_constraints()</tt>
where your hash is converted one item at a time using the normal Ruby <i>Enumerable</i>
routine <tt>#collect()</tt>. Which is where the side-effect happens.<br>
<br>
Try this in irb:<br>
<br>
<pre>$ irb
irb(main):001:0> @params = {:cn => "Bilbo Baggins", :telephoneNumber => "416-277-4418", :mail => <a class="moz-txt-link-rfc2396E" href="mailto:bilbo@baggins.com">"bilbo@baggins.com"</a>}
</pre>
<pre>irb(main):002:0> @params.collect{|c| c}</pre>
<pre>=> [[:cn, "Bilbo Baggins"], [:telephoneNumber, "416-277-4418"], [:mail, <a class="moz-txt-link-rfc2396E" href="mailto:bilbo@baggins.com">"bilbo@baggins.com"</a>]]</pre>
<pre>irb(main):003:0> </pre>
<br>
and you will see that your hash has been converted into the array of
arrays. That's what happening in the gem once you strip away <tt>#convert_constraint()</tt>
etc.<br>
<br>
You have a choice of workarounds; the simplest of which is a separate
array <tt>@params_for_mock_user = @params.collect</tt> ; (null body
returns each element as above) and then <tt>User.should_receive(:update_attributes).with(@params_for_mock_user).<br>
<br>
</tt>It might be worth <a
href="http://rubyforge.org/tracker/?atid=3152&group_id=797&func=browse">filing
an RFE</a> on this as it's counter-intuitive and likely to bite others
as well<br>
<tt><br>
</tt>Hope this helps.<br>
<br>
Rgds,<br>
Jerry<br>
<br>
<br>
James Hughes wrote:
<blockquote
cite="mid765a2c230702141600j33b98be7w22dab72e5c2cbc10@mail.gmail.com"
type="cite">
<pre wrap="">Hi,
I have this setup block:
setup do
session[:login] = 'jhughes'
@user = mock("user")
User.stub!(:find).and_return(@user)
@params = {:cn => "Bilbo Baggins",
:telephoneNumber => "416-277-4418",
:mail => <a class="moz-txt-link-rfc2396E" href="mailto:bilbo@baggins.com">"bilbo@baggins.com"</a>}
end
And then this spec:
specify "should update and save the attributes for user" do
@user.should_receive(:update_attributes).with(@params).and_return(true)
post :update, :id => "jhughes", :user => @params
end
This fails like this:
Mock 'user' expected :update_attributes with ([:telephoneNumber,
"416-277-4418"], [:mail, <a class="moz-txt-link-rfc2396E" href="mailto:bilbo@baggins.com">"bilbo@baggins.com"</a>], [:cn, "Bilbo Baggins"])
but received it with ({"cn"=>"Bilbo Baggins",
"telephoneNumber"=>"416-277-4418", "mail"=><a class="moz-txt-link-rfc2396E" href="mailto:bilbo@baggins.com">"bilbo@baggins.com"</a>})
Puzzling, especially since inspecting the @params variable just before
the should_receive shows the expected hash.
What am I doing wrong?
James
_______________________________________________
rspec-users mailing list
<a class="moz-txt-link-abbreviated" href="mailto:rspec-users@rubyforge.org">rspec-users@rubyforge.org</a>
<a class="moz-txt-link-freetext" href="http://rubyforge.org/mailman/listinfo/rspec-users">http://rubyforge.org/mailman/listinfo/rspec-users</a>
</pre>
</blockquote>
</body>
</html>