J
jeem
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 @[email protected]
result
end
def restoreKlassNew
@klass.restoreNew
end
def verify
raise VerifyFailure.new, "Expected
#[email protected]}
(e-mail address removed)==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
def testItResizesTheImage
imageNew=ClassMethodMocker.new(Magick::Image,:new)
image=FlexMock.new
imageNew.handle { |imagePath| assert_equal(@imagePath,imagePage);
image }
image.mock_handle
# 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 @[email protected]
result
end
def restoreKlassNew
@klass.restoreNew
end
def verify
raise VerifyFailure.new, "Expected
#[email protected]}
(e-mail address removed)==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