From: "Jesús Gabriel y Galán" Date: 2010-08-02T15:20:52+09:00 Subject: Re: Mocking a method with a block On Sun, Aug 1, 2010 at 10:40 AM, Fernando Guillen wrote: > Jesús Gabriel y Galán wrote: >> One option would be to change the start method of Net::POP3 to do >> exactly what you describe > > This is a good idea. > > I can open the class Net::POP3 and redefine the method .start. > > Now, how can I organize this to charge the redefinition of the method at > the beginning of the test and revert it at the end of the test. You can use alias_method to "save" a copy of the original method with another name. You can do this in the setup of your tests, and revert back to that version in the teardown: irb(main):001:0> class A irb(main):002:1> def self.test irb(main):003:2> "original test" irb(main):004:2> end irb(main):005:1> end irb(main):013:0> class A irb(main):014:1> class << self irb(main):015:2> alias_method :orig_test, :test irb(main):016:2> end irb(main):017:1> end # at this point you can call A.test and A.orig_test and both do the same # now you can create a new version of the method: irb(main):020:0> class A irb(main):021:1> def self.test irb(main):022:2> "new test, original was [#{orig_test}]" irb(main):023:2> end irb(main):024:1> end => nil irb(main):025:0> A.test => "new test, original was [original test]" irb(main):026:0> A.orig_test => "original test" As you can see, you can still refer to the original method. To put it back: irb(main):027:0> class A irb(main):028:1> class << self irb(main):029:2> alias_method :test, :orig_test irb(main):030:2> end irb(main):031:1> end => # irb(main):032:0> A.test => "original test" (this leaves the orig_test method around, but I don't think that would be a problem). > > I mean, if I have a file that redefine the Net::POP3.start method I can > 'require' it but I don't know how to 'un-require' it. > > Also I would like to simulate that the Net::POP3.start charges my mails > array (different on every test) and if I redefine this method in a > generic way I don't know how to use my mails array inside the redefined > method. If this is just for running a test you could use a global variable or a constant: irb(main):034:0> MY_EMAILS = %w{a b c d e} => ["a", "b", "c", "d", "e"] irb(main):035:0> class A irb(main):036:1> class << self irb(main):037:2> alias_method :orig_test, :test irb(main):038:2> def test irb(main):039:3> "my emails: #{MY_EMAILS}" irb(main):040:3> end irb(main):041:2> end irb(main):042:1> end => nil irb(main):043:0> A.test => "my emails: abcde" You can also look at class_eval and define_method to build a closure around your emails' variable (sorry, don't have time now to do that, I'll come back later if you need it). Jesus.