tags:

views:

48

answers:

2

How can I mock the initialize method on a ruby class?

I'm doing some testing and want to mock out the object that is created from a new call.

I tried to write a few things and none of them seemed to get the mock class to return from the new call. It just keeps returning the normal, expected object.

EDIT:

one attempt -

class MockReminderTimingInfoParser < ReminderTimingInfoParser
  def new(blank)
    ReminderTimingInfoParserForTest.new
  end
end

describe ReminderParser do
  parser = ReminderParser.new(MockReminderTimingInfoParser)

  it "should parse line into a Reminder" do
    parser.parse(" doesnt matter  \"message\"").should == Reminder.new('message', ReminderTimingInfo.new([DaysOfWeek.new([:sundays])], [1]))
  end
end

class ReminderTimingInfoParserForTest
  include TimingInfoParser

  def parse_section(section); [DaysOfWeek.new([:sundays]), 1] end

  def reminder_times_converter(times); times end
end
A: 

Could you inherit the class and then supply your own initialize?

Daniel
I tried that, and it doesn't seem to work. I'll post my code in an edit to the question.
Alex Baranosky
+1  A: 
class MockReminderTimingInfoParser < ReminderTimingInfoParser
  def new(blank)
    ReminderTimingInfoParserForTest.new
  end
end

Here, you are defining a method called new for all instances of the class MockReminderTimingInfoParser. In your question, you mention that you want to hook into instance creation. However, in Ruby, instance creation is not done by instance methods. Obviously, this cannot work, since in order to call an instance method, you'd need to have an instance first!

Instead, instances are created by calling a factory method (commonly called new) on the class.

In other words, in order to create an instance of MockReminderTimingInfoParser, you would call MockReminderTimingInfoParser.new, but you have defined a method MockReminderTimingInfoParser#new. In order to call the method you have defined, you would have to call MockReminderTimingInfoParser.new.new.

You need to define a method on MockReminderTimingInfoParser's singleton class. There's several ways to do that. One way would be just mimicking the way you would call the method:

def MockReminderTimingInfoParser.new(blank)
  ReminderTimingInfoParserForTest.new
end

Another would be opening up MockReminderTimingInfoParser's singleton class:

class << MockReminderTimingInfoParser
  def new(blank)
    ReminderTimingInfoParserForTest.new
  end
end

However, in both of these cases, MockReminderTimingInfoParser obviously has to exist first. Given that you need to define the class anyway, here's the most idiomatic way of defining methods on a class's (or module's) singleton class:

class MockReminderTimingInfoParser < ReminderTimingInfoParser
  def self.new(blank)
    ReminderTimingInfoParserForTest.new
  end
end
Jörg W Mittag
either way neither seems to be working. IF you have an example snippet of code that works, I'd love to see it.
Alex Baranosky
thanks! I just figured this out via some blog posts, but your answer is excellent, thanks again. Some of your code gives me cleaner ways to do what I got working.
Alex Baranosky
I especially liek this syntax:
Alex Baranosky
def ReminderTimingInfoParser.new(*args) ReminderTimingInfoParserForTest.newend
Alex Baranosky