How do I write an RSpec test to unit-test this interesting metaprogramming code?

Posted by Kyle Kaitan on Stack Overflow See other posts from Stack Overflow or by Kyle Kaitan
Published on 2010-05-23T13:49:46Z Indexed on 2010/05/23 13:50 UTC
Read the original article Hit count: 252

Filed under:
|
|
|

Here's some simple code that, for each argument specified, will add specific get/set methods named after that argument. If you write attr_option :foo, :bar, then you will see #foo/foo= and #bar/bar= instance methods on Config:

module Configurator
  class Config
    def initialize()
      @options = {}
    end

    def self.attr_option(*args)
      args.each do |a|
        if not self.method_defined?(a)
          define_method "#{a}" do
            @options[:"#{a}"] ||= {}
          end

          define_method "#{a}=" do |v|
            @options[:"#{a}"] = v
          end
        else
          throw Exception.new("already have attr_option for #{a}")
        end
      end
    end
  end
end

So far, so good. I want to write some RSpec tests to verify this code is actually doing what it's supposed to. But there's a problem! If I invoke attr_option :foo in one of the test methods, that method is now forever defined in Config. So a subsequent test will fail when it shouldn't, because foo is already defined:

  it "should support a specified option" do
    c = Configurator::Config
    c.attr_option :foo
    # ...
  end

  it "should support multiple options" do
    c = Configurator::Config
    c.attr_option :foo, :bar, :baz   # Error! :foo already defined
                                     # by a previous test.
    # ...
  end

Is there a way I can give each test an anonymous "clone" of the Config class which is independent of the others?

© Stack Overflow or respective owner

Related posts about ruby

Related posts about metaprogramming