Is there a way to do something like this? class Foo def self.hello(name) "Hello #{name}!" end end Foo.expects(:bar).with("Carl").once assert_equal "Hello Carl!", Foo.hello Basically, my problem is that once you set an expectation, the original code is never executed and is not tested. However, it''s still very useful to set expectations to make sure the right arguments are passed to certain methods. The above example surely is over simplistic, but in a real world scenario, it totally makes sense. Is it possible to do something like this in Mocha as it is right now. If not, is that something you''d consider implementing? Thanks! /carl
Brian Takita discusses this functionality in his RR mocking framework under the moniker Mock Proxy. http://pivots.pivotallabs.com/users/brian/blog/articles/352-introducing-rr Not sure if I''ve posted to this about the pattern before, but it looks really useful, especially if it could be combined with traditional mocking techniques. On Tue, May 20, 2008 at 11:50 AM, Carl Mercier <carl at carlmercier.com> wrote:> Is there a way to do something like this? > > class Foo > def self.hello(name) > "Hello #{name}!" > end > end > > Foo.expects(:bar).with("Carl").once > > assert_equal "Hello Carl!", Foo.hello > > Basically, my problem is that once you set an expectation, the original code > is never executed and is not tested. However, it''s still very useful to set > expectations to make sure the right arguments are passed to certain methods. > The above example surely is over simplistic, but in a real world scenario, > it totally makes sense. > > Is it possible to do something like this in Mocha as it is right now. If > not, is that something you''d consider implementing? > > Thanks! > > /carl > > > > > > > > _______________________________________________ > mocha-developer mailing list > mocha-developer at rubyforge.org > http://rubyforge.org/mailman/listinfo/mocha-developer >
I wish Mocha supported this "out of the box" with this syntax: User.expects(:find).with(1) # returns the "real" row from the database User.expects(:find).with(1).returns(mocked_row) # returns a fake row and to have something explicitly return nil (without running the real code): Foo.expects(:bar).returns(nil) It''s probably too late to change the way .expects work right now, however. /c On 20-May-08, at 5:55 PM, Duncan Beevers wrote:> Brian Takita discusses this functionality in his RR mocking framework > under the moniker Mock Proxy. > > http://pivots.pivotallabs.com/users/brian/blog/articles/352-introducing-rr > > Not sure if I''ve posted to this about the pattern before, but it looks > really useful, especially if it could be combined with traditional > mocking techniques.
On May 21, 2008, at 10:56 AM, Carl Mercier wrote:> I wish Mocha supported this "out of the box" with this syntax: > > User.expects(:find).with(1) # returns the "real" row from the > database > User.expects(:find).with(1).returns(mocked_row) # returns a fake rowIn my opinion, I don''t find that useful. If I want the real row from the database to brought in, I wouldn''t use mocking. I only use expects / stubs when I want to alter and/or assert behavior.> and to have something explicitly return nil (without running the > real code): > Foo.expects(:bar).returns(nil)I''m too lazy to check right now, but I thought that was the current behavior. Foo.expects(:bar) Foo.bar => nil
I think you missed my point. I -do- want the real database row, but I also want to make sure that the "find" method is called with the right parameters and x number of times. So this is not really mocking, just setting expectations about what will be called and with what arguments. On 21-May-08, at 4:32 PM, Zach Moazeni wrote:> On May 21, 2008, at 10:56 AM, Carl Mercier wrote: > >> I wish Mocha supported this "out of the box" with this syntax: >> >> User.expects(:find).with(1) # returns the "real" row from the >> database >> User.expects(:find).with(1).returns(mocked_row) # returns a fake row > > In my opinion, I don''t find that useful. If I want the real row from > the database to brought in, I wouldn''t use mocking. I only use > expects / stubs when I want to alter and/or assert behavior. > >> and to have something explicitly return nil (without running the >> real code): >> Foo.expects(:bar).returns(nil) > > I''m too lazy to check right now, but I thought that was the current > behavior. > > Foo.expects(:bar) > Foo.bar => nil > > _______________________________________________ > mocha-developer mailing list > mocha-developer at rubyforge.org > http://rubyforge.org/mailman/listinfo/mocha-developer
> So this is not really mocking, just setting expectations about what > will be called and with what arguments.Isn''t that the current functionality though? If I do a... Model.expects(:find).with(:all, {:conditions => [''id = ?'', 1]}).returns(@model) I get the arguments tested because Model.find(:all) would fail and tell me I forgot the :conditions hash. Now I do understand that the return value would not be tested by Mocha against what I provided... but if I''m testing return values I would just do. @model.should_not be_nil :: Justin Reagor :: justinwr at gmail.com On May 21, 2008, at 4:35 PM, Carl Mercier wrote:> I think you missed my point. I -do- want the real database row, > but I also want to make sure that the "find" method is called with > the right parameters and x number of times. > > So this is not really mocking, just setting expectations about what > will be called and with what arguments. > > On 21-May-08, at 4:32 PM, Zach Moazeni wrote: > >> On May 21, 2008, at 10:56 AM, Carl Mercier wrote: >> >>> I wish Mocha supported this "out of the box" with this syntax: >>> >>> User.expects(:find).with(1) # returns the "real" row from the >>> database >>> User.expects(:find).with(1).returns(mocked_row) # returns a fake >>> row >> >> In my opinion, I don''t find that useful. If I want the real row >> from the database to brought in, I wouldn''t use mocking. I only >> use expects / stubs when I want to alter and/or assert behavior. >> >>> and to have something explicitly return nil (without running the >>> real code): >>> Foo.expects(:bar).returns(nil) >> >> I''m too lazy to check right now, but I thought that was the >> current behavior. >> >> Foo.expects(:bar) >> Foo.bar => nil >> >> _______________________________________________ >> mocha-developer mailing list >> mocha-developer at rubyforge.org >> http://rubyforge.org/mailman/listinfo/mocha-developer > > _______________________________________________ > mocha-developer mailing list > mocha-developer at rubyforge.org > http://rubyforge.org/mailman/listinfo/mocha-developer
On May 21, 2008, at 4:35 PM, Carl Mercier wrote:> I think you missed my point. I -do- want the real database row, but > I also want to make sure that the "find" method is called with the > right parameters and x number of times.I''ll chalk it up to different testing strategies using mocking, but to my recollection, I''ve never come across the need for my code to execute real code as well as assert the parameters and number of times the function was called. But I''m speaking from my experience, and my needs which are most likely different from yours. If I''m concerned with the parameters, I''ll stub or expect it (depending on the situation), and return either an existing object or stub. But even when I''m testing ActiveRecord, I rarely send back an instance of an ActiveRecord object. If the code under test requires a real instance, and can''t succinctly use a stub, it starts to smell as if the code is doing too much to that instance. Another thing to note, is that I''m a big fan of returning literals when behavior is not required on the return value itself. Car.stubs(:find).with(1).returns("the car") Car.stubs(:find).with(:all, :conditions => ["color = ?", "red"]).returns(["car 1", "car 2"]) This is very useful, and readable, when the return becomes a parameter for another function, or the return is used in an algorithm (like reversing an array). -Zach
Here''s a test file to illustrate what I''m saying. #------------- require File.dirname(__FILE__) + "/../test_helper" class BlehTest < Test::Unit::TestCase def foo(x) "bar #{x}" end def test_foo # fails, foo(1) returns nil # ideally, this test should pass and execute the foo # method since I didn''t specify a return value self.expects(:foo).with(1) assert_equal "bar 1", foo(1) end def test_foo2 # fails, foo(1) returns nil, foo is already mocked, # so totally understandable self.expects(:foo).with(1).returns(foo(1)) assert_equal "bar 1", foo(1) end def test_foo3 # works, but verbose and not very dry. very tricky # to do something like this in a real world scenario output = foo(1) self.expects(:foo).with(1).returns(output) assert_equal "bar 1", foo(1) # success end end #------------- On 21-May-08, at 4:51 PM, Justin Reagor wrote:>> So this is not really mocking, just setting expectations about what >> will be called and with what arguments. > > > Isn''t that the current functionality though?