From: jeem Date: 2005-03-15T23:00:21+09:00 Subject: Mocking new and other class methods Hello group. I wanted to be able to do something like this: def testItResizesTheImage imageNew=ClassMethodMocker.new(Magick::Image,:new) image=FlexMock.new imageNew.handle { |imagePath| assert_equal(@imagePath,imagePage); image } image.mock_handle(:somecall) { |etc| etc } # etc test_subj.doThatThing image.mock_verify imageNew.verify end So, I wrote a few loc to enable it (borrowing from FlexMock) for 'new' calls at least. I'm having second thoughts about how I implemented it, so I was hoping some in the ng might want to kick it around. My big concern with the current method (see below) is that the real new might not be "put back" if a coder doesn't use MockNew.use. I have other ways in mind to allow mocking of class methods, but they all seem to put up new hoops for coders to jump through, and make the resulting code less natural. Here's the code, excluding the tests: class Class public :alias_method end class Object def backupNew class << self alias_method :mocknew_backedup_new, :new end end @@newHandler={} def delegateNew(newHandler) module_eval { @@newHandler[self]=newHandler; def self.new(*args); @@newHandler[self].handleNew(*args); end } end def restoreNew class << self alias_method :new, :mocknew_backedup_new end end end class MockNew def initialize(klass,&block) klass.backupNew klass.delegateNew(self) @klass=klass @handlers=[] @callCount=0 handle(&block) if block_given? end def handleNew(*args) result=@handlers[@callCount].call(*args) @callCount += 1 restoreKlassNew if @callCoun...@handlers.length result end def restoreKlassNew @klass.restoreNew end def verify raise VerifyFailure.new, "Expected #...@handlers.length} cal...@handlers.length==1?'':'s'} to #{@klass}.new; received #{@callCount}." unless @callCount == @handlers.length end def handle(&block) @handlers << block end def self.use(klass) mockNew=new(klass) yield mockNew mockNew.verify ensure mockNew.restoreKlassNew end class VerifyFailure < StandardError end end