[rspec-users] render_to_string confusing ControllerSpec

Andrew Selder aselder at mac.com
Mon Jun 16 23:23:46 EDT 2008


David,

Valid point about the method needing some refactoring. But another key  
rule of refactoring is to have passing tests before refactoring.

This is one of the things that's a minor annoyance I have about rails,  
you can't associate views with models. The problem with the  
refactoring suggested is that render_to_string is a member of  
ActionController::Base, and moving it in to a string construction  
method in the model is complicated by no helpers available in the  
model, and that partial uses tons of helpers. So it's hard to move a  
generate_marker method to the model.

Regardless of all of the above, RSpec controller specs have issues  
when testing which template was rendered if you use render_to_string.

Andrew



On Jun 16, 2008, at 11:05 PM, David Chelimsky wrote:

> On Jun 16, 2008, at 9:19 PM, Andrew Selder wrote:
>
>> I updated the spec to look like this:
>>
>>   it "should render show template" do
>>     do_get
>>     controller.stub_render(:partial => "/properties/ 
>> map_info_box", :object => anything())
>>     response.should render_template('show')
>>   end
>>
>> and I still get the same failure and back trace.
>>
>> In addition to not working, the problem with stubbing out that  
>> render to string is that I can't then check for the presence of  
>> those strings in the final output.
>
> Well, therein lies the real problem :) This action is exhibiting a  
> number of code smells. I don't know how familiar you might be w/  
> that, but:
>
>  Long Method - a method that does too many things (I count at least  
> 10)
>  Feature Envy - one one object is doing work on another object's data
>
> There's also a lot of asking, violating the Tell Don't Ask principle.
>
> This block:
>
>  @props.each do |prop|
>    coords = prop.latlng
>    unless coords.lat == 0 || coords.lng == 0
>      prop.info_box = render_to_string(:partial => "/properties/ 
> map_info_box", :object => prop)
>      mark = prop.has_photos? ? "green" : "red"
>      marker = GMarker.new(coords, :title =>  
> prop_help.bubble_header(prop),\
>        :info_window => prop.info_box, :icon => Variable.new(mark))
>      @map.overlay_init marker
>      @markers << marker
>    end
>  end
>
> .. could become:
>
>  @props.each do |prop|
>    @markers << prop.generate_marker if prop.needs_marker?
>  end
>
> Much simpler to test at that point! I'd recommend heading down that  
> path.
>
> HTH,
> David
>
>
>
>> Thanks,
>>
>> Andrew
>>
>> On Jun 16, 2008, at 10:03 PM, David Chelimsky wrote:
>>
>>> On Jun 16, 2008, at 8:59 PM, Andrew Selder wrote:
>>>
>>>> Here's the back trace
>>>>
>>>> 1)
>>>> 'SearchesController handling GET /searches/1 should render show  
>>>> template' FAILED
>>>> expected "show", got "properties/_map_info_box"
>>>> /Users/aselder/BostonLogic/one_system/vendor/plugins/rspec/lib/ 
>>>> spec/expectations.rb:52:in `fail_with'
>>>> /Users/aselder/BostonLogic/one_system/vendor/plugins/rspec/lib/ 
>>>> spec/expectations/handler.rb:25:in `handle_matcher'
>>>> /Users/aselder/BostonLogic/one_system/vendor/plugins/rspec/lib/ 
>>>> spec/expectations/extensions/object.rb:31:in `should'
>>>> ./spec/controllers/searches_controller_spec.rb:26:
>>>> /Users/aselder/BostonLogic/one_system/vendor/plugins/rspec/lib/ 
>>>> spec/example/example_methods.rb:84:in `instance_eval'
>>>> /Users/aselder/BostonLogic/one_system/vendor/plugins/rspec/lib/ 
>>>> spec/example/example_methods.rb:84:in  
>>>> `run_with_description_capturing'
>>>> /Users/aselder/BostonLogic/one_system/vendor/plugins/rspec/lib/ 
>>>> spec/example/example_methods.rb:21:in `execute'
>>>> /opt/local/lib/ruby/1.8/timeout.rb:48:in `timeout'
>>>> /Users/aselder/BostonLogic/one_system/vendor/plugins/rspec/lib/ 
>>>> spec/example/example_methods.rb:18:in `execute'
>>>> /Users/aselder/BostonLogic/one_system/vendor/plugins/rspec/lib/ 
>>>> spec/example/example_group_methods.rb:303:in `execute_examples'
>>>> /Users/aselder/BostonLogic/one_system/vendor/plugins/rspec/lib/ 
>>>> spec/example/example_group_methods.rb:302:in `each'
>>>> /Users/aselder/BostonLogic/one_system/vendor/plugins/rspec/lib/ 
>>>> spec/example/example_group_methods.rb:302:in `execute_examples'
>>>> /Users/aselder/BostonLogic/one_system/vendor/plugins/rspec/lib/ 
>>>> spec/example/example_group_methods.rb:130:in `run'
>>>> /Users/aselder/BostonLogic/one_system/vendor/plugins/rspec/lib/ 
>>>> spec/runner/example_group_runner.rb:22:in `run'
>>>> /Users/aselder/BostonLogic/one_system/vendor/plugins/rspec/lib/ 
>>>> spec/runner/example_group_runner.rb:21:in `each'
>>>> /Users/aselder/BostonLogic/one_system/vendor/plugins/rspec/lib/ 
>>>> spec/runner/example_group_runner.rb:21:in `run'
>>>> /Users/aselder/BostonLogic/one_system/vendor/plugins/rspec/lib/ 
>>>> spec/runner/options.rb:106:in `run_examples'
>>>> /Users/aselder/BostonLogic/one_system/vendor/plugins/rspec/lib/ 
>>>> spec/runner/command_line.rb:19:in `run'
>>>> script/spec:4:
>>>>
>>>> And here's the controller action:
>>>>
>>>> def show
>>>> @search = Search.find(params[:id])
>>>> if @search.too_many_results?
>>>>   message_to_new "Your search returned too many results (#{@search.count 
>>>> }). Please narrow your criteria and search again."
>>>>   return
>>>> elsif @search.no_results?
>>>>   message_to_new "Your search returned no results. Please change  
>>>> your criteria and search again."
>>>>   return
>>>> end
>>>> init_map
>>>> @props = @search.do_search
>>>> @markers = []
>>>> @props.each do |prop|
>>>>   coords = prop.latlng
>>>>   unless coords.lat == 0 || coords.lng == 0
>>>>     prop.info_box = render_to_string(:partial => "/properties/ 
>>>> map_info_box", :object => prop)
>>>
>>> This is the line that's causing you trouble. Try stubbing this one  
>>> out as well:
>>>
>>> response.stub_render(:partial => "/properties/ 
>>> map_info_box", :object => anything())
>>>
>>> Let us know if it works.
>>>
>>> Cheers,
>>> David
>>>
>>>>
>>>>     mark = prop.has_photos? ? "green" : "red"
>>>>     marker = GMarker.new(coords, :title =>  
>>>> prop_help.bubble_header(prop), :info_window =>  
>>>> prop.info_box, :icon => Variable.new(mark))
>>>>     @map.overlay_init marker
>>>>     @markers << marker
>>>>   end
>>>> end
>>>> unless @markers.empty?
>>>>   @map.center_zoom_on_points_init(*(@markers.collect {|x|  
>>>> x.point}))
>>>> else
>>>>   @map.center_zoom_init(@search.center, 12)
>>>> end
>>>> end
>>>>
>>>> Thanks,
>>>>
>>>> Andrew
>>>>
>>>> On Jun 16, 2008, at 9:34 PM, David Chelimsky wrote:
>>>>
>>>>> On Jun 16, 2008, at 2:58 PM, Andrew Selder wrote:
>>>>>
>>>>>> Hi all,
>>>>>>
>>>>>> I have a controller I'm trying to spec out, and I'm running  
>>>>>> into some issues with render_to_string.
>>>>>>
>>>>>> Basically, the show gets an array of objects, calls  
>>>>>> render_to_string for each of them, and then renders the show  
>>>>>> template.
>>>>>>
>>>>>> So I have the standard spec:
>>>>>>
>>>>>>
>>>>>> it "should render show template" do
>>>>>> do_get
>>>>>> response.should render_template('show')
>>>>>> end
>>>>>>
>>>>>>
>>>>>> but when I run the spec I get the following failure:
>>>>>>
>>>>>> 'SearchesController handling GET /searches/1 should render show  
>>>>>> template' FAILED
>>>>>> expected "show", got "properties/_map_info_box"
>>>>>>
>>>>>>
>>>>>> Does anybody have any ideas?
>>>>>
>>>>> Please post the controller action and the full backtrace:
>>>>>
>>>>> script/spec spec/controller/path/to/the/spec.rb -fsb
>>>>>
>>>>> Thx
>>>>> _______________________________________________
>>>>> rspec-users mailing list
>>>>> rspec-users at rubyforge.org
>>>>> http://rubyforge.org/mailman/listinfo/rspec-users
>>>>
>>>> _______________________________________________
>>>> rspec-users mailing list
>>>> rspec-users at rubyforge.org
>>>> http://rubyforge.org/mailman/listinfo/rspec-users
>>>
>>> _______________________________________________
>>> rspec-users mailing list
>>> rspec-users at rubyforge.org
>>> http://rubyforge.org/mailman/listinfo/rspec-users
>>
>> _______________________________________________
>> rspec-users mailing list
>> rspec-users at rubyforge.org
>> http://rubyforge.org/mailman/listinfo/rspec-users
>
> _______________________________________________
> rspec-users mailing list
> rspec-users at rubyforge.org
> http://rubyforge.org/mailman/listinfo/rspec-users



More information about the rspec-users mailing list