On Sun, Aug 1, 2010 at 10:40 AM, Fernando Guillen
<fguillen.mail / gmail.com> wrote:
> Jes=FAs Gabriel y Gal=E1n 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
=3D> nil
irb(main):025:0> A.test
=3D> "new test, original was [original test]"
irb(main):026:0> A.orig_test
=3D> "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
=3D> #<Class:A>
irb(main):032:0> A.test
=3D> "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 =3D %w{a b c d e}
=3D> ["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
=3D> nil
irb(main):043:0> A.test
=3D> "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.