Why would that be a chore I hear you ask?
Because the singleton in question had several configuration options.
Most of which were file based.
So out of the ~60 specs, 50 of them were for error conditions.
(File missing, folder not readable, not JSON, JSON but with invalid stanzas etc)
The problem was that each test had to start with a clean slate.
The singleton class must be pristine and new each run.
How the hell do you do that?
Unload the class, then reload it.
I fiddled about quite a bit with this, so I've put together a simple project that illustrates how this is done.
The bottom line is that you have to send :remove_const and the class name to the module or whatever your class is defined in.
For example, say a class is defined in a file skavee_bloopsie.rb thus:
module Skavee class Bloopsie end end
Then this is what you run to unload and reload it:
Skavee.send(:remove_const, :Bloopsie)
This works at any depth of modules:
module A module B module C class Z def ohai 'ohai!' end end end end end A::B::C.send(:remove_const, :Z)
You can test this yourself by copying and pasting this into irb:
module A module B module C class Z def ohai 'ohai!' end end end end end a = A::B::C::Z.new => #<A::B::C::Z:0x007fc78c9b1dc8> puts a.ohai => "ohai!" A::B::C.send(:remove_const, :Z) => A::B::C::Z b = A::B::C::Z.new => NameError: uninitialized constant A::B::C::Z And here's the Gotcha! a.ohai => "ohai!"
Wha? Well it's obvious. The instance is still being referenced.
So be careful out there people.
An example gem is available via my repo at https://github.com/ZenGirl/ruby-class-unloading
No comments:
Post a Comment