Bryan Helmkamp
2006-Oct-06 22:20 UTC
[mocha-developer] Expecting calls with two different parameters
Hello, I''ve just started using Mocha in the tests for my Rails app, and I''ve run across an issue with mocking a method that should be called with different parameters. How would I setup a mock that expects that a method will be called once with no paramaters, and a second time with a parameter? I''d be tempted to shortcut and just do something like foo.expects(:bar).times(2), but the value used as the parameter when calling it the second time is very important. Thoughts? -Bryan -- http://www.MyCongress.org/ -- coming soon
Kevin Clark
2006-Oct-07 03:13 UTC
[mocha-developer] Expecting calls with two different parameters
Someone correct me if I''m wrong, but I thought you could set multiple expectations on an object. On 10/6/06, Bryan Helmkamp <bhelmkamp at gmail.com> wrote:> Hello, > > I''ve just started using Mocha in the tests for my Rails app, and I''ve > run across an issue with mocking a method that should be called with > different parameters. > > How would I setup a mock that expects that a method will be called > once with no paramaters, and a second time with a parameter? I''d be > tempted to shortcut and just do something like > foo.expects(:bar).times(2), but the value used as the parameter when > calling it the second time is very important. > > Thoughts? > > -Bryan > > -- > http://www.MyCongress.org/ -- coming soon > _______________________________________________ > mocha-developer mailing list > mocha-developer at rubyforge.org > http://rubyforge.org/mailman/listinfo/mocha-developer >-- Kevin Clark http://glu.ttono.us
James Mead
2006-Oct-07 09:35 UTC
[mocha-developer] Expecting calls with two different parameters
On 10/6/06, Bryan Helmkamp <bhelmkamp at gmail.com> wrote:> How would I setup a mock that expects that a method will be called > once with no paramaters, and a second time with a parameter? I''d be > tempted to shortcut and just do something like > foo.expects(:bar).times(2), but the value used as the parameter when > calling it the second time is very important.You shoud be able to do the following... def test_me object = mock() object.expects(:expected_method).with(:important_value) object.expects(:expected_method) object.expected_method(:important_value) object.expected_method(:another_value) end Is that what you mean? Calling expects() without a call to with() matches a call to the method with any parameters. -- James. http://blog.floehopper.org -------------- next part -------------- An HTML attachment was scrubbed... URL: http://rubyforge.org/pipermail/mocha-developer/attachments/20061007/175f1f8b/attachment.html
Bryan Helmkamp
2006-Oct-08 20:31 UTC
[mocha-developer] Expecting calls with two different parameters
Thanks, Kevin and James. The key is instead of writing the mock like this: foo.expects(:bar) foo.expects(:bar).with("something") You have to write it like this: foo.expects(:bar).with() foo.expects(:bar).with("something") The first example won''t work. If you don''t want to specify the paramaters passed in one of the method calls, you can do: foo.expects(:bar).times(2) foo.expects(:bar).with("something") And that works too. Thanks, -Bryan On 10/7/06, James Mead <jamesmead44 at gmail.com> wrote:> On 10/6/06, Bryan Helmkamp <bhelmkamp at gmail.com> wrote: > > How would I setup a mock that expects that a method will be called > > once with no paramaters, and a second time with a parameter? I''d be > > tempted to shortcut and just do something like > > foo.expects(:bar).times(2), but the value used as the parameter when > > calling it the second time is very important. > > You shoud be able to do the following... > > def test_me > object = mock() > object.expects(:expected_method).with(:important_value) > object.expects(:expected_method) > > object.expected_method(:important_value) > object.expected_method(:another_value) > end > > Is that what you mean? Calling expects() without a call to with() matches a > call to the method with any parameters. > -- > James. > http://blog.floehopper.org > _______________________________________________ > mocha-developer mailing list > mocha-developer at rubyforge.org > http://rubyforge.org/mailman/listinfo/mocha-developer > >-- http://www.MyCongress.org/ -- coming soon
James Mead
2006-Oct-09 07:51 UTC
[mocha-developer] Expecting calls with two different parameters
On 08/10/06, Bryan Helmkamp <bhelmkamp at gmail.com> wrote:> > Thanks, Kevin and James. The key is instead of writing the mock like > this: > > foo.expects(:bar) > foo.expects(:bar).with("something") > > You have to write it like this: > > foo.expects(:bar).with() > foo.expects(:bar).with("something") > > The first example won''t work. If you don''t want to specify the > paramaters passed in one of the method calls, you can do: > > foo.expects(:bar).times(2) > foo.expects(:bar).with("something") > > And that works too. > > Thanks, > > -Bryan >I''m glad you''ve worked it out - I''m still not clear what the issue was. It would be clearer if you showed the actual method calls as well as the expectations. I''m keen to observe the principle of least surprise, so please let me know if an aspect of the Mocha API didn''t work how you expected. -- James. http://blog.floehopper.org -------------- next part -------------- An HTML attachment was scrubbed... URL: http://rubyforge.org/pipermail/mocha-developer/attachments/20061009/5cb67b1d/attachment.html
Bryan Helmkamp
2006-Oct-09 13:41 UTC
[mocha-developer] Expecting calls with two different parameters
James, What I''m trying to do is mock the render call for my controller so that the views never get processed when I run my functional tests, but I can check that the correct view was going to be processed. The calls to render (in this case) are burried in Rails'' ActionPack code, since it is using the default view for the action. Here''s what I started with for the mock: @controller.expects(:render).with(:action => "edit") This doesn''t work on its own because when using the default view, Rails will call render once with no paramaters and once with the action specified. The error is: Unexpected message :render() sent to #<Mocha::Mock: 30458920> Similar expectations :render(:action => ''edit'') Basically, it''s a fundamental aspect of the mocking behavior that''s causing the issue. When a method is mocked for one call with one set of parameters, it is implied that the method is to be called exactly once with those exact parameters and no more. It seems like this might be too strict. On the other hand, to loosen up this requirement would mean it would take two method calls to achieve the current behavior: @controller.expects(:render).times(1) @controller.expects(:render).with(:action => "edit") I think it is interesting that the following won''t work for my example: @controller.expects(:render).times(2) @controller.expects(:render).with(:action => "edit") It results in: :render(:action => ''edit''): expected calls: 1, actual calls: 0 Even though the render method is called twice, and one of those calls is with the :action => "edit" parameter. It''s like the first expectation is blocking the second one from passing. Thoughts? -Bryan On 10/9/06, James Mead <jamesmead44 at gmail.com> wrote:> On 08/10/06, Bryan Helmkamp <bhelmkamp at gmail.com> wrote: > > Thanks, Kevin and James. The key is instead of writing the mock like > this: > > > > foo.expects(:bar) > > foo.expects(:bar).with("something") > > > > You have to write it like this: > > > > foo.expects(:bar).with() > > foo.expects(:bar).with("something") > > > > The first example won''t work. If you don''t want to specify the > > paramaters passed in one of the method calls, you can do: > > > > foo.expects(:bar).times(2) > > foo.expects (:bar).with("something") > > > > And that works too. > > > > Thanks, > > > > -Bryan > > > > I''m glad you''ve worked it out - I''m still not clear what the issue was. It > would be clearer if you showed the actual method calls as well as the > expectations. > > I''m keen to observe the principle of least surprise, so please let me know > if an aspect of the Mocha API didn''t work how you expected. > > -- > > James. > http://blog.floehopper.org > _______________________________________________ > mocha-developer mailing list > mocha-developer at rubyforge.org > http://rubyforge.org/mailman/listinfo/mocha-developer > >-- http://www.MyCongress.org/ -- coming soon
James Mead
2006-Oct-09 16:57 UTC
[mocha-developer] Expecting calls with two different parameters
On 09/10/06, Bryan Helmkamp <bhelmkamp at gmail.com> wrote:> > I think it is interesting that the following won''t work for my example: > > @controller.expects(:render).times(2) > @controller.expects(:render).with(:action => "edit") > > It results in: > > :render(:action => ''edit''): expected calls: 1, actual calls: 0 > > Even though the render method is called twice, and one of those calls > is with the :action => "edit" parameter. It''s like the first > expectation is blocking the second one from passing.Thanks for taking the time to explain more fully. I think part of the confusion comes from the fact that it''s not obvious that object.expects(:blah) matches calls to blah() with any parameters, whereas object.expects(:blah).with() matches only calls to blah() with no parameters. Your last example is interesting. You''re right that the first expectation is blocking the second. The first expectation that matches an incoming call has its ''actual'' count incremented. But it would be relatively straightforward to increment the count for ANY expectations that match. I need to think about whether it has any other ramifications. Interestingly, if you switch the order in which the expectations are setup you get a different error... @controller.expects(:render).with(:action => "edit") @controller.expects(:render).times(2) :render(): expected calls: 2, actual calls: 1 This is because the call to render() drops through to the second expectation, but the call to render(:action => "edit") is matched by the first expectation. -- James. http://blog.floehopper.org -------------- next part -------------- An HTML attachment was scrubbed... URL: http://rubyforge.org/pipermail/mocha-developer/attachments/20061009/c1f5a387/attachment.html
Kevin Clark
2006-Oct-09 18:05 UTC
[mocha-developer] Expecting calls with two different parameters
Though I like the interface less, flexmock''s constraints are significantly more flexible (which is usually something I dislike). You may want to see if it makes sense as far as mocking renders go. It''s bundled with rails, so there''s no reason you couldn''t mix mocking libraries. On 10/9/06, Bryan Helmkamp <bhelmkamp at gmail.com> wrote:> James, > > What I''m trying to do is mock the render call for my controller so > that the views never get processed when I run my functional tests, but > I can check that the correct view was going to be processed. The calls > to render (in this case) are burried in Rails'' ActionPack code, since > it is using the default view for the action. Here''s what I started > with for the mock: > > @controller.expects(:render).with(:action => "edit") > > This doesn''t work on its own because when using the default view, > Rails will call render once with no paramaters and once with the > action specified. The error is: > > Unexpected message :render() sent to #<Mocha::Mock: 30458920> > Similar expectations :render(:action => ''edit'') > > Basically, it''s a fundamental aspect of the mocking behavior that''s > causing the issue. When a method is mocked for one call with one set > of parameters, it is implied that the method is to be called exactly > once with those exact parameters and no more. > > It seems like this might be too strict. On the other hand, to loosen > up this requirement would mean it would take two method calls to > achieve the current behavior: > > @controller.expects(:render).times(1) > @controller.expects(:render).with(:action => "edit") > > I think it is interesting that the following won''t work for my example: > > @controller.expects(:render).times(2) > @controller.expects(:render).with(:action => "edit") > > It results in: > > :render(:action => ''edit''): expected calls: 1, actual calls: 0 > > Even though the render method is called twice, and one of those calls > is with the :action => "edit" parameter. It''s like the first > expectation is blocking the second one from passing. > > Thoughts? > > -Bryan > > > On 10/9/06, James Mead <jamesmead44 at gmail.com> wrote: > > On 08/10/06, Bryan Helmkamp <bhelmkamp at gmail.com> wrote: > > > Thanks, Kevin and James. The key is instead of writing the mock like > > this: > > > > > > foo.expects(:bar) > > > foo.expects(:bar).with("something") > > > > > > You have to write it like this: > > > > > > foo.expects(:bar).with() > > > foo.expects(:bar).with("something") > > > > > > The first example won''t work. If you don''t want to specify the > > > paramaters passed in one of the method calls, you can do: > > > > > > foo.expects(:bar).times(2) > > > foo.expects (:bar).with("something") > > > > > > And that works too. > > > > > > Thanks, > > > > > > -Bryan > > > > > > > I''m glad you''ve worked it out - I''m still not clear what the issue was. It > > would be clearer if you showed the actual method calls as well as the > > expectations. > > > > I''m keen to observe the principle of least surprise, so please let me know > > if an aspect of the Mocha API didn''t work how you expected. > > > > -- > > > > James. > > http://blog.floehopper.org > > _______________________________________________ > > mocha-developer mailing list > > mocha-developer at rubyforge.org > > http://rubyforge.org/mailman/listinfo/mocha-developer > > > > > > > -- > http://www.MyCongress.org/ -- coming soon > _______________________________________________ > mocha-developer mailing list > mocha-developer at rubyforge.org > http://rubyforge.org/mailman/listinfo/mocha-developer >-- Kevin Clark http://glu.ttono.us
Bryan Helmkamp
2006-Oct-09 21:09 UTC
[mocha-developer] Expecting calls with two different parameters
Thanks for the tip on Flexmock, Kevin... I''ll check it out. James -- I think it''s least surprising to increment the count for all the expectations that match, but you''re certainly right that it may have other ramifications. Let me know what you figure out. -Bryan On 10/9/06, Kevin Clark <kevin.clark at gmail.com> wrote:> Though I like the interface less, flexmock''s constraints are > significantly more flexible (which is usually something I dislike). > You may want to see if it makes sense as far as mocking renders go. > It''s bundled with rails, so there''s no reason you couldn''t mix mocking > libraries. > > > On 10/9/06, Bryan Helmkamp <bhelmkamp at gmail.com> wrote: > > James, > > > > What I''m trying to do is mock the render call for my controller so > > that the views never get processed when I run my functional tests, but > > I can check that the correct view was going to be processed. The calls > > to render (in this case) are burried in Rails'' ActionPack code, since > > it is using the default view for the action. Here''s what I started > > with for the mock: > > > > @controller.expects(:render).with(:action => "edit") > > > > This doesn''t work on its own because when using the default view, > > Rails will call render once with no paramaters and once with the > > action specified. The error is: > > > > Unexpected message :render() sent to #<Mocha::Mock: 30458920> > > Similar expectations :render(:action => ''edit'') > > > > Basically, it''s a fundamental aspect of the mocking behavior that''s > > causing the issue. When a method is mocked for one call with one set > > of parameters, it is implied that the method is to be called exactly > > once with those exact parameters and no more. > > > > It seems like this might be too strict. On the other hand, to loosen > > up this requirement would mean it would take two method calls to > > achieve the current behavior: > > > > @controller.expects(:render).times(1) > > @controller.expects(:render).with(:action => "edit") > > > > I think it is interesting that the following won''t work for my example: > > > > @controller.expects(:render).times(2) > > @controller.expects(:render).with(:action => "edit") > > > > It results in: > > > > :render(:action => ''edit''): expected calls: 1, actual calls: 0 > > > > Even though the render method is called twice, and one of those calls > > is with the :action => "edit" parameter. It''s like the first > > expectation is blocking the second one from passing. > > > > Thoughts? > > > > -Bryan > > > > > > On 10/9/06, James Mead <jamesmead44 at gmail.com> wrote: > > > On 08/10/06, Bryan Helmkamp <bhelmkamp at gmail.com> wrote: > > > > Thanks, Kevin and James. The key is instead of writing the mock like > > > this: > > > > > > > > foo.expects(:bar) > > > > foo.expects(:bar).with("something") > > > > > > > > You have to write it like this: > > > > > > > > foo.expects(:bar).with() > > > > foo.expects(:bar).with("something") > > > > > > > > The first example won''t work. If you don''t want to specify the > > > > paramaters passed in one of the method calls, you can do: > > > > > > > > foo.expects(:bar).times(2) > > > > foo.expects (:bar).with("something") > > > > > > > > And that works too. > > > > > > > > Thanks, > > > > > > > > -Bryan > > > > > > > > > > I''m glad you''ve worked it out - I''m still not clear what the issue was. It > > > would be clearer if you showed the actual method calls as well as the > > > expectations. > > > > > > I''m keen to observe the principle of least surprise, so please let me know > > > if an aspect of the Mocha API didn''t work how you expected. > > > > > > -- > > > > > > James. > > > http://blog.floehopper.org > > > _______________________________________________ > > > mocha-developer mailing list > > > mocha-developer at rubyforge.org > > > http://rubyforge.org/mailman/listinfo/mocha-developer > > > > > > > > > > > > -- > > http://www.MyCongress.org/ -- coming soon > > _______________________________________________ > > mocha-developer mailing list > > mocha-developer at rubyforge.org > > http://rubyforge.org/mailman/listinfo/mocha-developer > > > > > -- > Kevin Clark > http://glu.ttono.us > _______________________________________________ > mocha-developer mailing list > mocha-developer at rubyforge.org > http://rubyforge.org/mailman/listinfo/mocha-developer >-- http://www.MyCongress.org/ -- coming soon