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 <[email protected]> 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
> [email protected]
> http://rubyforge.org/mailman/listinfo/rspec-users
>
_______________________________________________
rspec-users mailing list
[email protected]
http://rubyforge.org/mailman/listinfo/rspec-users