Robert Klemme
3/15/2005 3:12:00 PM
"jeem" <jeem.hughes@gmail.com> schrieb im Newsbeitrag
news:1110898032.514026.227640@f14g2000cwb.googlegroups.com...
> Let me try again.
>
> class CodeIWantToTest
> def foo(bar)
> f = File.new(@userPath+bar)
> #more
> f.close
> end
> end
>
> class Tests < Test::Unit::TestCase
> def testFoo
> fileNew=MockNew.new(File)
> mockFile=FlexMock.new
> fileNew.handle { |path| assert_equal('/home/usrname/etc/bob',path);
> mockFile }
> #more
> subj.foo('bob')
> fileNew.verify
> end
> end
>
> I the test above, I want foo to call File.new. If I were to make a
> mock class (cl_fake) in my test, I couldn't expect foo to call it,
> because foo is not aware of cl_fake. Foo knows about File.
Ah, ok. Thx for clarifying.
> Maybe I'm missing something. Can you write the example above with the
> method from your post?
Well, you had to redefine constant File, which might not be such a good
idea.
Then what about a transaction based approach? Like
module Kernel
private
def mock(obj, sym, mock)
cl = class <<obj; self; end
old = obj.method sym
cl.class_eval { define_method(sym, &mock) }
begin
yield
ensure
cl.class_eval { define_method(sym, &old) }
end
end
end
>> mock File, :new, lambda {|*f| "new! #{f.inspect}"} do
?> File.new "foo", "r"
>> end
=> "new! [\"foo\", \"r\"]"
You can even nest that:
>> mock File, :new, lambda {|*f| "new! #{f.inspect}" } do
?> p File.new( "foo", "r" )
>>
?> mock File, :new, lambda {|*f| "new 2: #{f.inspect}" } do
?> p File.new( "bar", "w" )
>> end
>>
?> p File.new( "foo", "r" )
>> end
"new! [\"foo\", \"r\"]"
"new 2: [\"bar\", \"w\"]"
"new! [\"foo\", \"r\"]"
=> nil
Kind regards
robert