[rspec-users] Odd parameter munging with with()

David Chelimsky dchelimsky at gmail.com
Tue Feb 20 11:12:03 EST 2007


On 2/20/07, David Chelimsky <dchelimsky at gmail.com> wrote:
> On 2/20/07, Jerry West <jerry.west at ntlworld.com> wrote:
> >
> >
> >
> >  So, I still say my app code and my reduction look conceptually the
> > same, but I'm stumped as to why they don't behave the same way
> >
> >  David seems to have picked that up.  Ignore my blatherings about
> > HashArgConstraint (though the rest is valid).
> >
> >  Here's another twist under  Rails 1.2.2 (which may not be supported but
> > works fine for what I am doing so far).
> >
> >  Basically, a different expectation seems to be set up depending on whether
> > the argument to get/post is a variable or not.  That cannot be right.  What
> > am I missing?
> >
> >  require File.dirname(__FILE__) + '/../spec_helper'
> >
> >  class TestController < ActionController::Base
> >    def index() self.amethod(params) end
> >  end
> >
> >  context 'a test controller' do
> >    controller_name :test
> >
> >    setup do
> >      @plist = { "id" => "1", "param2" => "bar" }
> >
> > controller.should_receive(:amethod).with(@plist).and_return(true)
> >    end
> >
> >   specify "should pass a hash to #with (1)" do
> >      get :index, "id" => "1", "param2" => "bar"
> >    end
> >    specify "should pass a hash to #with (2)" do
> >      get :index, { "id" => "1", "param2" => "bar" }
> >    end
> >    specify "should pass a hash to #with (3)" do
> >      get :index, @plist
> >    end
> >  end
> >
> >  $ spec -cfs spec/controllers/test_controller_spec.rb
> >  /usr/bin/spec:17:Warning: require_gem is obsolete.  Use gem instead.
> >  /home/jjw/rails/playground/config/boot.rb:29:Warning:
> > require_gem is obsolete.  Use gem instead.
> >
> >  a test controller
> >  - should pass a hash to #with (1) (FAILED - 1)
> >  - should pass a hash to #with (2) (FAILED - 2)
> >  - should pass a hash to #with (3) (FAILED - 3)
> >
> >  1)
> >  'a test controller should pass a hash to #with (1)' FAILED (ignore the
> > failure, look at the expectation)
> >  #<TestController:0xb70a1df8> expected :amethod with (["param2", "bar"],
> > ["id", "1"]) but received it with ({"action"=>"index", "id"=>"1",
> > "param2"=>"bar", "controller"=>"test"})
> >  (eval):3:in `amethod'
> >  ./spec/controllers/test_controller_spec.rb:4:in `index'
> >  /usr/local/lib/site_ruby/1.8/benchmark.rb:300:in `measure'
> >  ./spec/controllers/test_controller_spec.rb:13:
> >
> >  2)
> >  'a test controller should pass a hash to #with (2)' FAILED (ignore the
> > failure, look at the expectation)
> >  #<TestController:0xb7093820> expected :amethod with (["param2", "bar"],
> > ["id", "1"]) but received it with ({"action"=>"index", "id"=>"1",
> > "param2"=>"bar", "controller"=>"test"})
> >  (eval):3:in `amethod'
> >  ./spec/controllers/test_controller_spec.rb:4:in `index'
> >  /usr/local/lib/site_ruby/1.8/benchmark.rb:300:in `measure'
> >  ./spec/controllers/test_controller_spec.rb:18:
> >
> >  3)
> >  'a test controller should pass a hash to #with (3)' FAILED (ignore the
> > failure, look at the expectation)
> >  #<TestController:0xb708cf34> expected :amethod with ([:only_path, true],
> > ["param2", "bar"], ["id", "1"], [:action, :index]) but received it with
> > ({"action"=>"index", "id"=>"1", "param2"=>"bar", "controller"=>"test"})
> >  (eval):3:in `amethod'
> >  ./spec/controllers/test_controller_spec.rb:4:in `index'
> >  /usr/local/lib/site_ruby/1.8/benchmark.rb:300:in `measure'
> >  ./spec/controllers/test_controller_spec.rb:23:
> >
> >  Finished in 0.022612 seconds
> >
> >  3 specifications, 3 failures
> >
> >
> >  Where the heck did the :only_path stuff come from in the expectation for
> > case 3??  They weren't there in ArgumentExpectation#initialize.
> >
> >  As expected, creating the 'right' expectation  (@plist = { "id" =>
> > "1","param2" => "bar", "action" => "index", "controller" => "test" } )
> > allows the spec to pass in cases 1 & 2, but #3 still fails.
>
> Here's the same output w/ the latest trunk. Note that it shows #with
> correctly receiving a Hash now.
>
> 1)
> Spec::Mocks::MockExpectationError in 'a test controller should pass a
> hash to #with (1)'
> #<TestController:0x2578854> expected :amethod with ({"param2"=>"bar",
> "id"=>"1"}) but received it with ({"action"=>"index", "id"=>"1",
> "param2"=>"bar", "controller"=>"test"})
> ./spec/controllers/temp_spec.rb:4:in `index'
> ./spec/controllers/temp_spec.rb:16:
>
> 2)
> Spec::Mocks::MockExpectationError in 'a test controller should pass a
> hash to #with (2)'
> #<TestController:0x2516ec4> expected :amethod with ({"param2"=>"bar",
> "id"=>"1"}) but received it with ({"action"=>"index", "id"=>"1",
> "param2"=>"bar", "controller"=>"test"})
> ./spec/controllers/temp_spec.rb:4:in `index'
> ./spec/controllers/temp_spec.rb:19:
>
> 3)
> Spec::Mocks::MockExpectationError in 'a test controller should pass a
> hash to #with (3)'
> #<TestController:0x2461d58> expected :amethod with ({:only_path=>true,
> "param2"=>"bar", "id"=>"1", :action=>:index}) but received it with
> ({"action"=>"index", "id"=>"1", "param2"=>"bar",
> "controller"=>"test"})
> ./spec/controllers/temp_spec.rb:4:in `index'
> ./spec/controllers/temp_spec.rb:22:
>
> I have NO idea yet about  :only_path. I'll keep you posted...

OK, I now have SOME idea, but I'm still trying to figure out
specifics. The following passes. Note that it uses @plist.dup each
time.

require File.dirname(__FILE__) + '/../spec_helper'

class TestController < ActionController::Base
  def index() self.amethod(params) end
end

context 'a test controller' do
  controller_name :test

  setup do
    @plist = { "id" => "1", "param2" => "bar" , "controller" =>
"test", "action" => "index" }
    controller.should_receive(:amethod).with(@plist.dup).and_return(true)
  end

 specify "should pass a hash to #with (1)" do
    get :index, "id" => "1", "param2" => "bar"
  end

  specify "should pass a hash to #with (2)" do
    get :index, { "id" => "1", "param2" => "bar" }
  end

  specify "should pass a hash to #with (3)" do
    get :index, @plist.dup
  end
end

If you search through Rails you'll find dozens of instances of
:only_path. So the problem SEEMS to be that by the time we reach the
third spec, @plist has been touched by Rails.

BTW - here's a variation that passes and allows you to deal only w/
the subset of keys you want.

context 'a test controller' do
  controller_name :test

  setup do
    controller.should_receive(:amethod).and_return(true) { |params|
      params["id"].should == "1"
      params["param2"].should == "bar"
    }
  end

 specify "should pass a hash to #with (1)" do
    get :index, "id" => "1", "param2" => "bar"
  end

  specify "should pass a hash to #with (2)" do
    get :index, { "id" => "1", "param2" => "bar" }
  end

  specify "should pass a hash to #with (3)" do
    @plist = { "id" => "1", "param2" => "bar" }
    get :index, @plist.dup
  end
end

Cheers,
David

>
> >
> >  rgds from "Confused of Hampshire".
> >
> >
> >
> >
> > _______________________________________________
> > rspec-users mailing list
> > rspec-users at rubyforge.org
> > http://rubyforge.org/mailman/listinfo/rspec-users
> >
>


More information about the rspec-users mailing list