[rspec-users] Mocking base class methods

Jeroen van Dijk jeroentjevandijk at gmail.com
Fri Mar 20 06:30:54 EDT 2009


Huray, got it solved! Hopefully you'll agree with this solution (thanks to
mocha sorry)


  describe "count_by_params" do
    it "should pass all the params and options to #scope_by_params" do
      params  = { :foo => 1, :bar => 2 }
      options = { :foo => 3, :bar => 4 }

      @base = ActiveRecord::Base
      @result = mock("query results", :count => 1)
      @base.expects(:scoped_by_params).with(params,
options).returns(@result)
      @base.count_by_params(params, options)
    end



On Thu, Mar 19, 2009 at 5:35 PM, Jeroen van Dijk <jeroentjevandijk at gmail.com
> wrote:

> 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/20090320/be5567e4/attachment-0001.html>


More information about the rspec-users mailing list