How can I safely mock a singleton without the mocked method living on outside the scope of the test method? I''ve run into this problem with mocking methods on globals (gasp!) in the past by doing something like def mock_my_global original = $my_global $my_global.expects(:foo).returns(''bar'') yield $my_global = original end Is there something similar I can do for a singleton? Right now I have this: def mock_my_singleton m = mock("my singleton") m.expects(:foo).returns(''bar'') MySingleton.expects(:instance).returns(m) yield end Thanks for your help. -justin list mods: I sent a previous message to the list but my membership was pending so my message is too. This message is more concise than my previous one so please do not approve it :)
On 21/08/07, Justin Perkins <justin at spiceworks.com> wrote:> > How can I safely mock a singleton without the mocked method living on > outside the scope of the test method?This is one of the things Mocha takes care of for you in the context of a test method. I''ve run into this problem with mocking methods on globals (gasp!) in> the past by doing something like > > def mock_my_global > original = $my_global > $my_global.expects(:foo).returns(''bar'') > yield > $my_global = original > end > > Is there something similar I can do for a singleton? Right now I have > this: > > def mock_my_singleton > m = mock("my singleton") > m.expects(:foo).returns(''bar'') > MySingleton.expects(:instance).returns(m) > yield > endDo something like the following... def test_me m = mock("my singleton") m.expects(:foo).returns(''bar'') MySingleton.stubs(:instance).returns(m) # Mocha modifies the MySingleton#instance method at this point. # From now until the end of the test it will return the mock. # At the end of the test it will be reverted to its original implementation. end You don''t need to explicitly revert the method to its original implementation - Mocha does it for you. list mods: I sent a previous message to the list but my membership> was pending so my message is too. This message is more concise than > my previous one so please do not approve it :)No problems. Thanks for letting me know. -- James. http://blog.floehopper.org
On Mon, 2007-08-20 at 20:26 -0500, Justin Perkins wrote:> How can I safely mock a singleton without the mocked method living on > outside the scope of the test method?This is how I did it: http://jonathanleighton.com/blog/testing-singleton-classes
> On Aug 21, 2007, at 3:45 AM, Jonathan Leighton wrote: > This is how I did it: > http://jonathanleighton.com/blog/testing-singleton-classesCan I define a teardown method in the test_helper or would your solution require a per-test-case teardown method to reload the singleton? -justin
On Aug 21, 2007, at 2:38 AM, James Mead wrote:> > This is one of the things Mocha takes care of for you in the > context of a > test method.That''s what I thought but I was getting weird behavior when I ran all the tests that led me to believe the mocked method was lingering around.> MySingleton.stubs(:instance).returns(m)That was it. As soon as I used stubs instead of expects, everything works fine. I believe that when you use expects on a singleton, the mock lingers after the test is complete. -justin
On Tue, 2007-08-21 at 12:28 -0500, Justin Perkins wrote:> > On Aug 21, 2007, at 3:45 AM, Jonathan Leighton wrote: > > This is how I did it: > > http://jonathanleighton.com/blog/testing-singleton-classes > > Can I define a teardown method in the test_helper or would your > solution require a per-test-case teardown method to reload the > singleton?I''m not sure why you''d want to do that? You''d only need to "reload" the Singleton when you are testing it, not in every single test. Maybe I''ve misunderstood something... Jon
On 21/08/07, Justin Perkins <justin at spiceworks.com> wrote:> > > On Aug 21, 2007, at 2:38 AM, James Mead wrote: > > > > This is one of the things Mocha takes care of for you in the > > context of a > > test method. > > That''s what I thought but I was getting weird behavior when I ran all > the tests that led me to believe the mocked method was lingering around. > > > MySingleton.stubs(:instance).returns(m) > > That was it. As soon as I used stubs instead of expects, everything > works fine. I believe that when you use expects on a singleton, the > mock lingers after the test is complete.That sounds wrong. "expects" should work as well. You may have found a bug. If you get the chance can you try and distill the failing scenario down to the smallest self-contained test you can and post it too the list. Thanks. -- James. http://blog.floehopper.org
On Aug 22, 2007, at 3:29 AM, Jonathan Leighton wrote:> I''m not sure why you''d want to do that? You''d only need to "reload" > the > Singleton when you are testing it, not in every single test. Maybe > I''ve > misunderstood something...In every test where I was mocking my singleton I would have to add an additional teardown method, since I''m retrofitting existing code to mock the singleton this would require more work than I think is necessary. Maybe I''m just misunderstanding the implementation? -justin