From aaron at tenderlovemaking.com Thu Mar 20 15:55:08 2008 From: aaron at tenderlovemaking.com (Aaron Patterson) Date: Thu, 20 Mar 2008 12:55:08 -0700 Subject: [Flexmock-users] mocking methods called from initialize Message-ID: <20080320195508.GA30023@mac-mini.lan> Hi, When mocking new instances of an object, when does flexmock override the mocked methods? I'm not sure how to ask this question without an example: class Foo def initialize; two; end def two; puts "hello"; end end class TestFoo < Test::Unit::TestCase def test_call_two flexmock(Foo).new_instances.should_receive(:two).and_return(10) Foo.new end end When I wrote that, I expected two() to return 10 like the mock says. But I see "hello" printed when I run the test. Are my expectations incorrect? If so, how can I mock the "two" method? Thanks! -- Aaron Patterson http://tenderlovemaking.com/ From pm at ubit.com Fri Mar 21 05:21:17 2008 From: pm at ubit.com (Paul McMahon) Date: Fri, 21 Mar 2008 18:21:17 +0900 Subject: [Flexmock-users] mocking methods called from initialize In-Reply-To: <20080320195508.GA30023@mac-mini.lan> References: <20080320195508.GA30023@mac-mini.lan> Message-ID: <47E37E0D.1070906@ubit.com> Aaron Patterson wrote: > Hi, > > When mocking new instances of an object, when does flexmock override the > mocked methods? I'm not sure how to ask this question without an > example: > > class Foo > def initialize; two; end > def two; puts "hello"; end > end > > class TestFoo < Test::Unit::TestCase > def test_call_two > flexmock(Foo).new_instances.should_receive(:two).and_return(10) > Foo.new > end > end > > When I wrote that, I expected two() to return 10 like the mock says. > But I see "hello" printed when I run the test. Are my expectations > incorrect? If so, how can I mock the "two" method? > > Thanks! > new_instances calls the original new method on the specified object, and creates a mock object out of the result of that call. As such, you cannot mock a method called in the initialize method of an object. If you are really set on mocking a method called in initialize, you could do something like: Foo.class_eval { def foo; 2; end } but, you should probably be listening to what this test case is telling you: that something smells. I normally avoid mocking any instance methods on the object I'm testing. If you need to mock an instance method, it is probably because you should split the object you are testing into multiple objects. You might consider refactoring your code to something like this: class Bar def two; puts "hello"; end end class Foo def initialize(bar); bar.two; end end class TestFoo < Test::Unit::TestCase def test_call_two mock_bar = flexmock.should_receive(:two).and_return(10).mock Foo.new(mock_bar) end end