[rspec-users] Mocking base class methods

Jeroen van Dijk jeroentjevandijk at gmail.com
Thu Mar 19 12:35:16 EDT 2009


Hi all,

I'm having the same problem as Tobi and I wanted to try Tobi mock solution
but unfortunately it does not work for me.

Here is a trivial example I want to test:

module ActiveRecord
  class Base
      def self.count_by_params(params = {}, options = {})
          scoped_by_params(params).count
      end
  end
end

And my spec:
module ActiveRecord
  class Base
    include BaseClassMock
  end
end

class DummyUser < ActiveRecord::Base
end

it "should pass all the params and options to #scope_by_params" do
   params  = { :foo => 1, :bar => 2 }
    options = { :foo => 3, :bar => 4 }
    @dummy = DummyUser
    @dummy.base_class.should_receive(:scope_by_params).with(params, options)
    DummyUser.count_by_params(params, options)
end

With the above example and Tobi's BaseClassMock module I'm getting
"undefined method `should_receive' for #<Object:0x188c164>". Btw, I also get
this when I do not use Tobi be it for for #<Class:0x188cdf8> instead of
Object.

Any suggestions on what I'm doing wrong or a different approach?

Cheers,
Jeroen



On Sat, Feb 21, 2009 at 10:24 PM, Tobi <listaccount at e-tobi.net> wrote:

> Zach Dennis wrote:
>
> > +1 to composition over inheritance here. Mocking at different layers
> > of an inheritance hierarchy sounds like trouble and screams to pull
> > that thing apart.
>
> Good point! I've already tried the composition approach. It solves the
> testabilitiy problems, but it doesn't feel right in this case.
>
> Inheritance seems to be the more natural approach. The C++ application
> will call virtual methods on the base class which should be overriden in a
> derived class. So it seems to make sense to have the same inheritance tree
> in the Ruby counter parts.
>
> If I would use composition, I would at least need to dynamically extend
> the referenced base class so I can override some of the methods that are
> the counter parts of the virtual C++ methods. And I would need to expose
> the referenced class to the C++ code.
>
> I've finally found a way to kinda mock the base class in some way:
>
> module BaseClassMock
>  attr_accessor :base
>
>  def self.included(klass)
>    class << klass
>      @@base_class = Object.new
>
>      def base_class
>        return @@base_class
>      end
>    end
>  end
>
>  def initialize(*args)
>    @@base_class.new(*args) if @@base_class.respond_to?(:new)
>    @base = Object.new
>  end
>
>  def method_missing(symbol, *args)
>    @base.send(symbol, *args)
>  end
> end
>
> Any base class (Swig classes in my case) should then be declared for RSpec
> like:
>
> module Swig
>  class Base; include BaseClassMock; end
> end
>
> And in the specs I can then do:
>
>    Derived.base_class.should_receive(:new).with('something')
>    d = Derived.new('something')
>
> or:
>
>    d = Derived.new
>    d.base.should_receive(:do_something)
>    d.do_something
>
> Tobias
> _______________________________________________
> rspec-users mailing list
> rspec-users at rubyforge.org
> http://rubyforge.org/mailman/listinfo/rspec-users
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://rubyforge.org/pipermail/rspec-users/attachments/20090319/b5cb74c3/attachment.html>


More information about the rspec-users mailing list