Mocking out a class object

A

Avdi Grimm

Okay, I'm trying to mock up a class object. It needs to do two
things:

1. Respond to #new with a object *I* provide, rather than a new
instance of the class; and
2. Contain a constant, such that code containing 'MyMockClass::FOO'
will work.

I can think of a naive implementation:

class MyMockClass
FOO="some value"
def self.set_instance(inst)
@instance=inst
end
def self.new(*)
return @instance
end
end

I'm wondering, though, is there a way to do this inline with
metaprogramming, and avoid defining the set_instance method? I've
tried something like this:

my_instance=...

Class.new :MyMockClass {
const_set :FOO, "some value"
define_method:)new) do |*|
return my_instance
end
}

But that doesn't work, because the define_method is creating an
instance method, not a class method. I've also tried to use a regular
old object, instead of a class object, but then the constant (FOO)
doesn't work. Any ideas?
 
D

David A. Black

Hi --

Okay, I'm trying to mock up a class object. It needs to do two
things:

1. Respond to #new with a object *I* provide, rather than a new
instance of the class; and
2. Contain a constant, such that code containing 'MyMockClass::FOO'
will work. [...]
I'm wondering, though, is there a way to do this inline with
metaprogramming, and avoid defining the set_instance method? I've
tried something like this:

my_instance=...

Class.new :MyMockClass {
const_set :FOO, "some value"
define_method:)new) do |*|
return my_instance
end
}

But that doesn't work, because the define_method is creating an
instance method, not a class method. I've also tried to use a regular
old object, instead of a class object, but then the constant (FOO)
doesn't work. Any ideas?

You're actually dealing with two classes: MyMockClass, and
MyMockClass's singleton class. So you would probably want to do
something like this:

# This is to make it look nicer (as per the
# pending RCR :)
module Kernel
def singleton_class
class << self; self; end
end
end

my_instance = ""

MyMockClass = Class.new {
self::FOO = "some value"
singleton_class.class_eval {
define_method:)new) {|*| my_instance}
}
}

p MyMockClass::FOO # "some value"
p MyMockClass.new # ""


David
 
R

Robert Klemme

Avdi Grimm said:
Okay, I'm trying to mock up a class object. It needs to do two
things:

1. Respond to #new with a object *I* provide, rather than a new
instance of the class; and
2. Contain a constant, such that code containing 'MyMockClass::FOO'
will work.

I can think of a naive implementation:

class MyMockClass
FOO="some value"
def self.set_instance(inst)
@instance=inst
end
def self.new(*)
return @instance
end
end

I'm wondering, though, is there a way to do this inline with
metaprogramming, and avoid defining the set_instance method? I've
tried something like this:

my_instance=...

Class.new :MyMockClass {
const_set :FOO, "some value"
define_method:)new) do |*|
return my_instance
end
}

But that doesn't work, because the define_method is creating an
instance method, not a class method. I've also tried to use a regular
old object, instead of a class object, but then the constant (FOO)
doesn't work. Any ideas?

You don't really need to make it so complicated IMHO:

class MockClass
def initialize(obj) @obj = obj end
def new() @obj end
end
=> 135024424

Alternative

class MockClass
def initialize(sym, obj)
@obj = obj
self.class.const_set sym, self
end
def new() @obj end
end
=> 135016960


Kind regards

robert
 
A

Avdi Grimm

David A. Black said:
You're actually dealing with two classes: MyMockClass, and
MyMockClass's singleton class. So you would probably want to do
something like this:

# This is to make it look nicer (as per the
# pending RCR :)
module Kernel
def singleton_class
class << self; self; end
end
end

my_instance = ""

MyMockClass = Class.new {
self::FOO = "some value"
singleton_class.class_eval {
define_method:)new) {|*| my_instance}
}
}

p MyMockClass::FOO # "some value"
p MyMockClass.new # ""


Thanks, that looks exactly like what I was looking for. It reveals
that I don't understand Ruby metaprogramming quite as well as I
thought, though. Would you mind explaining what singleton_instance is
doing, and how it differs from just using 'self' in the class
definition?

Thanks,

Avdi
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
474,170
Messages
2,570,925
Members
47,464
Latest member
Bobbylenly

Latest Threads

Top