Are partial mocks supposed to work in rails-rspec 2.0.0.beta.12? I''m trying to do things like view.stub(:current_user).and_return(@user) view.stub(:current_page?).and_return(false) However, when I do that, the view uses its "ordinary" functionality, in particular, assigns are no longer available as instance variables. Also, as regards mocking of partials (the rails ones) view.should_receive(:_render_partial). with(hash_including(:partial => "widget/row")) does not work as expected when render is called with objects like this render @article render @articles In these cases the hash[:partial] does not contain the path to the template, but the object(s). I''m right now having little fun in beta hell. That''s just how it is and by no means intend to distract you from your good work. I''m not yet reasonably familiar with Rails 3 and RSpec 2 and so I''m stumbling around alot in the sources and inch along in the debugger. One repeating point of bother is that often stacktraces are barely informative when delegation and dynamically generated code are in there. Unfortunately, I can''t think of a way to improve on this. Michael -- Michael Schuerig mailto:michael at schuerig.de http://www.schuerig.de/michael/
On Jun 20, 2010, at 3:19 PM, Michael Schuerig wrote:> Are partial mocks supposed to work in rails-rspec 2.0.0.beta.12? > > I''m trying to do things like > > view.stub(:current_user).and_return(@user) > view.stub(:current_page?).and_return(false) > > However, when I do that, the view uses its "ordinary" functionality, in > particular, assigns are no longer available as instance variables.Are you using rails beta 4? Before that release, the view() method returned a different object every time.> Also, as regards mocking of partials (the rails ones) > > view.should_receive(:_render_partial). > with(hash_including(:partial => "widget/row")) > > does not work as expected when render is called with objects like this > > render @article > render @articles > > In these cases the hash[:partial] does not contain the path to the > template, but the object(s).view.should_receive(:anything_at_all) is specifying rails internals, and has to be 100% precise. In this case, what you need to do is pretty invasive, and I wouldn''t recommend it, but here it is: require ''spec_helper'' describe "widgets/index.html.erb" do before(:each) do @widgets = assign(:widgets, [ stub_model(Widget), stub_model(Widget) ]) end it "renders a list of widgets" do view.stub(:_render_partial) view.should_receive(:_render_partial).with(hash_including(:partial => @widgets[0])) view.should_receive(:_render_partial).with(hash_including(:partial => @widgets[1])) render end end Can I hear a "blech!!!!!!!!!!!!". Unfortunately, there is not a better way to do this yet, and there may not be for some time. One of the big wins of rspec-rails-2 over rspec-rails-1 is that it does not rely on monkey patches (except in cases in which rails has changed since the last rails release, but rspec-rails needs to work with the last release). This drastically reduces the likelihood that rails releases will break rspec, which has been a big pain-point in the past. The downside of this is that we have to live with what Rails has to offer, and view tests are not nearly as robust as controller tests in rails. Yet :) Cheers, David> I''m right now having little fun in beta hell. That''s just how it is and > by no means intend to distract you from your good work. I''m not yet > reasonably familiar with Rails 3 and RSpec 2 and so I''m stumbling around > alot in the sources and inch along in the debugger. One repeating point > of bother is that often stacktraces are barely informative when > delegation and dynamically generated code are in there. Unfortunately, I > can''t think of a way to improve on this. > > Michael > > -- > Michael Schuerig > mailto:michael at schuerig.de > http://www.schuerig.de/michael/ > _______________________________________________ > rspec-users mailing list > rspec-users at rubyforge.org > http://rubyforge.org/mailman/listinfo/rspec-users
On Sunday 20 June 2010, David Chelimsky wrote:> On Jun 20, 2010, at 3:19 PM, Michael Schuerig wrote: > > Are partial mocks supposed to work in rails-rspec 2.0.0.beta.12? > > > > I''m trying to do things like > > > > view.stub(:current_user).and_return(@user) > > view.stub(:current_page?).and_return(false) > > > > However, when I do that, the view uses its "ordinary" > > functionality, in particular, assigns are no longer available as > > instance variables. > > Are you using rails beta 4? Before that release, the view() method > returned a different object every time.Yes, 3.0.0.beta4. TestCase#_view caches its return value.> view.should_receive(:anything_at_all) is specifying rails internals, > and has to be 100% precise. In this case, what you need to do is > pretty invasive, and I wouldn''t recommend it, but here it is: > > require ''spec_helper'' > > describe "widgets/index.html.erb" do > before(:each) do > @widgets = assign(:widgets, [ > stub_model(Widget), > stub_model(Widget) > ]) > end > > it "renders a list of widgets" do > view.stub(:_render_partial) > > view.should_receive(:_render_partial).with(hash_including(:partial > => @widgets[0])) > view.should_receive(:_render_partial).with(hash_including(:partial > => @widgets[1])) > > render > end > end > > Can I hear a "blech!!!!!!!!!!!!". > > Unfortunately, there is not a better way to do this yet, and there > may not be for some time.It''s okay, if I hide away the yucky bits in a helper method. # spec/support/partial_helpers.rb module PartialHelpers def should_render(options) options.assert_valid_keys(:partial, :count) view.should_receive(:_render_partial). with(hash_including(:partial => options[:partial])) end def should_not_render(options) options.assert_valid_keys(:partial, :count) view.should_not_receive(:_render_partial). with(hash_including(:partial => options[:partial])) end end # in spec/spec_helpers.rb config.include PartialHelpers, :example_group => { :description => lambda { |description| # FIXME this is a kludge as there is # currently (rspec 2.0.0.beta.12) # apparently no other way to identify a view # example group. description =~ /\.html\.erb$/ } } Michael -- Michael Schuerig mailto:michael at schuerig.de http://www.schuerig.de/michael/
On Jun 20, 2010, at 5:18 PM, Michael Schuerig wrote:> > # in spec/spec_helpers.rb > config.include PartialHelpers, :example_group => { > :description => lambda { |description| > # FIXME this is a kludge as there is > # currently (rspec 2.0.0.beta.12) > # apparently no other way to identify a view > # example group. > description =~ /\.html\.erb$/ > } > }Here''s how rspec-rails-2 does it: http://github.com/rspec/rspec-rails/blob/master/lib/rspec/rails/example/view_example_group.rb#L106
On Monday 21 June 2010, David Chelimsky wrote:> On Jun 20, 2010, at 5:18 PM, Michael Schuerig wrote: > > # in spec/spec_helpers.rb > > > > config.include PartialHelpers, :example_group => { > > > > :description => lambda { |description| > > : > > # FIXME this is a kludge as there is > > # currently (rspec 2.0.0.beta.12) > > # apparently no other way to identify a view > > # example group. > > description =~ /\.html\.erb$/ > > > > } > > > > } > > Here''s how rspec-rails-2 does it: > http://github.com/rspec/rspec-rails/blob/master/lib/rspec/rails/exam > ple/view_example_group.rb#L106Thanks, that''s better. Michael -- Michael Schuerig mailto:michael at schuerig.de http://www.schuerig.de/michael/
On Sunday 20 June 2010, Michael Schuerig wrote:> Are partial mocks supposed to work in rails-rspec 2.0.0.beta.12? > > I''m trying to do things like > > view.stub(:current_user).and_return(@user) > view.stub(:current_page?).and_return(false) > > However, when I do that, the view uses its "ordinary" functionality, > in particular, assigns are no longer available as instance > variables.I''ve found the reason: rspec- rails-2.0.0.beta.12/lib/rspec/rails/monkey/action_view/test_case.rb def _view @_view ||= begin view = ActionView::Base.new(ActionController::Base.view_paths, _assigns, @controller) ... view end end #_view (and #view in turn) creates just one ActionView::Base instance the first time it is called. That''s as it is intended. The effect is, however, that only assigns up to that point are passed to that instance. Consequently, later assigns are ignored. Michael -- Michael Schuerig mailto:michael at schuerig.de http://www.schuerig.de/michael/
On Jun 22, 2010, at 8:27 AM, Michael Schuerig wrote:> On Sunday 20 June 2010, Michael Schuerig wrote: >> Are partial mocks supposed to work in rails-rspec 2.0.0.beta.12? >> >> I''m trying to do things like >> >> view.stub(:current_user).and_return(@user) >> view.stub(:current_page?).and_return(false) >> >> However, when I do that, the view uses its "ordinary" functionality, >> in particular, assigns are no longer available as instance >> variables. > > I''ve found the reason: > > rspec- > rails-2.0.0.beta.12/lib/rspec/rails/monkey/action_view/test_case.rb > > def _view > @_view ||= begin > view = ActionView::Base.new(ActionController::Base.view_paths, > _assigns, @controller) > ... > view > end > end > > #_view (and #view in turn) creates just one ActionView::Base instance > the first time it is called. That''s as it is intended. The effect is, > however, that only assigns up to that point are passed to that instance. > Consequently, later assigns are ignored.Stubs and assigns are unrelated, so even though this might be a bug, I don''t think it''s the cause of what you''re seeing.
On Tuesday 22 June 2010, David Chelimsky wrote:> On Jun 22, 2010, at 8:27 AM, Michael Schuerig wrote:> > #_view (and #view in turn) creates just one ActionView::Base > > instance the first time it is called. That''s as it is intended. > > The effect is, however, that only assigns up to that point are > > passed to that instance. Consequently, later assigns are ignored. > > Stubs and assigns are unrelated, so even though this might be a bug, > I don''t think it''s the cause of what you''re seeing.It is. If I put all the assign(:x, value) before I first access #view, everything works as expected. The problem I had is entirely unrelated to stubs. It''s just that when I do things in this order view.stub(:something).and_return(''foo'') assign(:bar, 10) The assign doesn''t have an effect. I might as well have view.flash[:notice] = ''Something is rotten.'' assign(:bar, 10) and the effect would be the same. Assigns that come after the view is first initialized are ignored. Michael -- Michael Schuerig mailto:michael at schuerig.de http://www.schuerig.de/michael/
On Jun 22, 2010, at 9:58 AM, Michael Schuerig wrote:> On Tuesday 22 June 2010, David Chelimsky wrote: >> On Jun 22, 2010, at 8:27 AM, Michael Schuerig wrote: > >>> #_view (and #view in turn) creates just one ActionView::Base >>> instance the first time it is called. That''s as it is intended. >>> The effect is, however, that only assigns up to that point are >>> passed to that instance. Consequently, later assigns are ignored. >> >> Stubs and assigns are unrelated, so even though this might be a bug, >> I don''t think it''s the cause of what you''re seeing. > > It is. If I put all the assign(:x, value) before I first access #view, > everything works as expected. The problem I had is entirely unrelated to > stubs.Well, to be fair, the initial problem you cited in this thread (even in the subject line) is "partial mocks", not "assigns." That said, yes, this is a bug. I''ll see if we can do something about that in Rails proper rather than rspec, which is just decorating the rails behavior. Cheers, David> It''s just that when I do things in this order > > view.stub(:something).and_return(''foo'') > assign(:bar, 10) > > The assign doesn''t have an effect. I might as well have > > view.flash[:notice] = ''Something is rotten.'' > assign(:bar, 10) > > and the effect would be the same. Assigns that come after the view is > first initialized are ignored.
On Jun 22, 2010, at 10:06 AM, David Chelimsky wrote:> > On Jun 22, 2010, at 9:58 AM, Michael Schuerig wrote: > >> On Tuesday 22 June 2010, David Chelimsky wrote: >>> On Jun 22, 2010, at 8:27 AM, Michael Schuerig wrote: >> >>>> #_view (and #view in turn) creates just one ActionView::Base >>>> instance the first time it is called. That''s as it is intended. >>>> The effect is, however, that only assigns up to that point are >>>> passed to that instance. Consequently, later assigns are ignored. >>> >>> Stubs and assigns are unrelated, so even though this might be a bug, >>> I don''t think it''s the cause of what you''re seeing. >> >> It is. If I put all the assign(:x, value) before I first access #view, >> everything works as expected. The problem I had is entirely unrelated to >> stubs. > > Well, to be fair, the initial problem you cited in this thread (even in the subject line) is "partial mocks", not "assigns." > > That said, yes, this is a bug. I''ll see if we can do something about that in Rails proper rather than rspec, which is just decorating the rails behavior.https://rails.lighthouseapp.com/projects/8994-ruby-on-rails/tickets/4931> > Cheers, > David > >> It''s just that when I do things in this order >> >> view.stub(:something).and_return(''foo'') >> assign(:bar, 10) >> >> The assign doesn''t have an effect. I might as well have >> >> view.flash[:notice] = ''Something is rotten.'' >> assign(:bar, 10) >> >> and the effect would be the same. Assigns that come after the view is >> first initialized are ignored. > >
On Tuesday 22 June 2010, David Chelimsky wrote:> On Jun 22, 2010, at 10:06 AM, David Chelimsky wrote: > > On Jun 22, 2010, at 9:58 AM, Michael Schuerig wrote:> >>> Stubs and assigns are unrelated, so even though this might be a > >>> bug, I don''t think it''s the cause of what you''re seeing. > >> > >> It is. If I put all the assign(:x, value) before I first access > >> #view, everything works as expected. The problem I had is > >> entirely unrelated to stubs. > > > > Well, to be fair, the initial problem you cited in this thread > > (even in the subject line) is "partial mocks", not "assigns."Yes, indeed. That''s because I was confused by the behavior I was seeing. I found the root cause only because I had to dig in there for another reason. Michael -- Michael Schuerig mailto:michael at schuerig.de http://www.schuerig.de/michael/