From: Robert Dober Date: 2010-05-24T20:13:19+09:00 Subject: Re: How do I write an RSpec test to unit-test this interesting metaprogramming code? On Sun, May 23, 2010 at 4:00 PM, James Wenton wrote: > I'm a little stumped by this problem. 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 Caleb is right, c is not a good name ;), however lambda{ c.attr_option..... }.should raise_error( WhatWasIt) I call it WhatWasIt because you really should define your own Exception, e.g. IllegalMonitorState = Class::new RuntimeError please take care to subclass RuntimeError, subclassing Exception is waaaay toooo general. HTH R. > > Is there a way I can give each test an anonymous "clone" of the > `Config` class which is independent of the others? > > -- The best way to predict the future is to invent it. -- Alan Kay