Rails model association collections allow you to do nifty things like: article.comments.find(:all, :conditions => {:created_at > 1.day.ago}) Has anyone found a good way to mock this up? I''m currently doing this: @comment1 = mock_model(Comment) comments = mock(Array) comments.stub!(:find).and_return([@comment1]) @article = mock_model(Article) @article.stub!(:comments).and_return(comments) I don''t like this, because of that intermediate ''comments'' object, whose only purpose is so that i can stub the chained method. I''d like to do something like this: @comment1 = mock_model(Comment) @article = mock_model(Article, :comments => mock(Array, :find => [@comment1])) But trying this causes an error: "Mock ''Array'' received unexpected message :find with (:all, ...)" because you can''t inline stubs with ordinary `mock`. I can replace it with `mock_model`, but this feels unclean. Has anyone come across a good ''best-practice'' solution to this problem? TIA, Paul Sadauskas
On 7/18/07, Paul <psadauskas at absolute-performance.com> wrote:> Rails model association collections allow you to do nifty things like: > > article.comments.find(:all, :conditions => {:created_at > 1.day.ago}) > > Has anyone found a good way to mock this up? I''m currently doing this: > > @comment1 = mock_model(Comment) > comments = mock(Array) > comments.stub!(:find).and_return([@comment1]) > > @article = mock_model(Article) > @article.stub!(:comments).and_return(comments) > > I don''t like this, because of that intermediate ''comments'' object, whose > only purpose is so that i can stub the chained method. I''d like to do > something like this: > > @comment1 = mock_model(Comment) > > @article = mock_model(Article, :comments => mock(Array, :find => > [@comment1])) > > But trying this causes an error: "Mock ''Array'' received unexpected > message :find with (:all, ...)" because you can''t inline stubs with > ordinary `mock`. I can replace it with `mock_model`, but this feels unclean. > > Has anyone come across a good ''best-practice'' solution to this problem?You can use the stub() method instead of mock() to inline method stubs: @article = mock_model( Article, :comments => stub(Array, :find => [@comment1]) ) The mock() method works differently because it does different stuff w/ the Hash under the covers.> > TIA, > Paul Sadauskas > > _______________________________________________ > rspec-users mailing list > rspec-users at rubyforge.org > http://rubyforge.org/mailman/listinfo/rspec-users >
Any chance of some prettier syntax for that? ------- Courtenay On Jul 18, 2007, at 2:30 PM, "David Chelimsky" <dchelimsky at gmail.com> wrote:> On 7/18/07, Paul <psadauskas at absolute-performance.com> wrote: >> Rails model association collections allow you to do nifty things >> like: >> >> article.comments.find(:all, :conditions => {:created_at > >> 1.day.ago}) >> >> Has anyone found a good way to mock this up? I''m currently doing >> this: >> >> @comment1 = mock_model(Comment) >> comments = mock(Array) >> comments.stub!(:find).and_return([@comment1]) >> >> @article = mock_model(Article) >> @article.stub!(:comments).and_return(comments) >> >> I don''t like this, because of that intermediate ''comments'' object, >> whose >> only purpose is so that i can stub the chained method. I''d like to do >> something like this: >> >> @comment1 = mock_model(Comment) >> >> @article = mock_model(Article, :comments => mock(Array, :find => >> [@comment1])) >> >> But trying this causes an error: "Mock ''Array'' received unexpected >> message :find with (:all, ...)" because you can''t inline stubs with >> ordinary `mock`. I can replace it with `mock_model`, but this feels >> unclean. >> >> Has anyone come across a good ''best-practice'' solution to this >> problem? > > You can use the stub() method instead of mock() to inline method > stubs: > > @article = mock_model( > Article, :comments => stub(Array, :find => [@comment1]) > ) > > The mock() method works differently because it does different stuff w/ > the Hash under the covers. > >> >> TIA, >> Paul Sadauskas >> >> _______________________________________________ >> 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
Any chance of some prettier syntax for that? ------- Courtenay On Jul 18, 2007, at 2:30 PM, "David Chelimsky" <dchelimsky at gmail.com> wrote:> On 7/18/07, Paul <psadauskas at absolute-performance.com> wrote: >> Rails model association collections allow you to do nifty things >> like: >> >> article.comments.find(:all, :conditions => {:created_at > 1.day.ago}) >> >> Has anyone found a good way to mock this up? I''m currently doing >> this: >> >> @comment1 = mock_model(Comment) >> comments = mock(Array) >> comments.stub!(:find).and_return([@comment1]) >> >> @article = mock_model(Article) >> @article.stub!(:comments).and_return(comments) >> >> I don''t like this, because of that intermediate ''comments'' object, >> whose >> only purpose is so that i can stub the chained method. I''d like to do >> something like this: >> >> @comment1 = mock_model(Comment) >> >> @article = mock_model(Article, :comments => mock(Array, :find => >> [@comment1])) >> >> But trying this causes an error: "Mock ''Array'' received unexpected >> message :find with (:all, ...)" because you can''t inline stubs with >> ordinary `mock`. I can replace it with `mock_model`, but this feels >> unclean. >> >> Has anyone come across a good ''best-practice'' solution to this >> problem? > > You can use the stub() method instead of mock() to inline method > stubs: > > @article = mock_model( > Article, :comments => stub(Array, :find => [@comment1]) > ) > > The mock() method works differently because it does different stuff w/ > the Hash under the covers. > >> >> TIA, >> Paul Sadauskas >> >> _______________________________________________ >> 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
I eventually ended up using this, from a somewhat-related post to this list a couple months ago: def assoc_mock(stubs = {}) proxy = mock(''association_proxy'') stubs.each do |method, ret| proxy.stub!(method).and_return(ret) end proxy end Then I can do something like I wanted: @comment = mock_model(Comment) @article = mock_model(Article, :comments => (@comment = assoc_mock(:find => [@comment]))) But this works just like the stub!(Foo, :method => return). I might keep mine, though, its a little more explicit as to what the ''in-between'' collection is. Thanks, Paul David Chelimsky wrote:> On 7/18/07, Paul <psadauskas at absolute-performance.com> wrote: > >> Rails model association collections allow you to do nifty things like: >> >> article.comments.find(:all, :conditions => {:created_at > 1.day.ago}) >> >> Has anyone found a good way to mock this up? I''m currently doing this: >> >> @comment1 = mock_model(Comment) >> comments = mock(Array) >> comments.stub!(:find).and_return([@comment1]) >> >> @article = mock_model(Article) >> @article.stub!(:comments).and_return(comments) >> >> I don''t like this, because of that intermediate ''comments'' object, whose >> only purpose is so that i can stub the chained method. I''d like to do >> something like this: >> >> @comment1 = mock_model(Comment) >> >> @article = mock_model(Article, :comments => mock(Array, :find => >> [@comment1])) >> >> But trying this causes an error: "Mock ''Array'' received unexpected >> message :find with (:all, ...)" because you can''t inline stubs with >> ordinary `mock`. I can replace it with `mock_model`, but this feels unclean. >> >> Has anyone come across a good ''best-practice'' solution to this problem? >> > > You can use the stub() method instead of mock() to inline method stubs: > > @article = mock_model( > Article, :comments => stub(Array, :find => [@comment1]) > ) > > The mock() method works differently because it does different stuff w/ > the Hash under the covers. > > >> TIA, >> Paul Sadauskas >> >> _______________________________________________ >> 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 >
On 7/18/07, court3nay <court3nay at gmail.com> wrote:> Any chance of some prettier syntax for that?There''s always a chance. What do you propose?> > ------- > Courtenay > > On Jul 18, 2007, at 2:30 PM, "David Chelimsky" <dchelimsky at gmail.com> > wrote: > > > On 7/18/07, Paul <psadauskas at absolute-performance.com> wrote: > >> Rails model association collections allow you to do nifty things > >> like: > >> > >> article.comments.find(:all, :conditions => {:created_at > > >> 1.day.ago}) > >> > >> Has anyone found a good way to mock this up? I''m currently doing > >> this: > >> > >> @comment1 = mock_model(Comment) > >> comments = mock(Array) > >> comments.stub!(:find).and_return([@comment1]) > >> > >> @article = mock_model(Article) > >> @article.stub!(:comments).and_return(comments) > >> > >> I don''t like this, because of that intermediate ''comments'' object, > >> whose > >> only purpose is so that i can stub the chained method. I''d like to do > >> something like this: > >> > >> @comment1 = mock_model(Comment) > >> > >> @article = mock_model(Article, :comments => mock(Array, :find => > >> [@comment1])) > >> > >> But trying this causes an error: "Mock ''Array'' received unexpected > >> message :find with (:all, ...)" because you can''t inline stubs with > >> ordinary `mock`. I can replace it with `mock_model`, but this feels > >> unclean. > >> > >> Has anyone come across a good ''best-practice'' solution to this > >> problem? > > > > You can use the stub() method instead of mock() to inline method > > stubs: > > > > @article = mock_model( > > Article, :comments => stub(Array, :find => [@comment1]) > > ) > > > > The mock() method works differently because it does different stuff w/ > > the Hash under the covers. > > > >> > >> TIA, > >> Paul Sadauskas > >> > >> _______________________________________________ > >> 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 >