Jonathan Leighton
2007-Jul-16 21:39 UTC
[mocha-developer] Set the return value to "same as block"
It would be good to be able to set the return value to be the same as the return value of the block. I am trying to test opening a file in a block and reading from it. It would be nice to use code like this: object.stubs(:open).with("/path/to/file", "r").yields( stub(:read => "The file contents") ).returns(from_block) Which would make open() take the return value of the block. So this app code would work: def my_method open("/path/to/file", "r") { |file| file.read } end and this wouldn''t work (because the return value of the block is not the contents of the file): def my_method open("/path/to/file", "r") do |file| file.read puts "Stolid in my guilt, clutching it like a girl with a stuffed bunny, I failed to follow." end end -- Jonathan Leighton, Web Developer http://jonathanleighton.com/
James Mead
2007-Jul-18 08:45 UTC
[mocha-developer] Set the return value to "same as block"
I''m a bit confused as to what you are trying to test - there are no expects or asserts in your examples. Can you give a simple but complete example with both test and code. In particular, are you trying to test the functionality of the method or the block? -- James. http://blog.floehopper.org
John Wilger
2007-Jul-18 18:21 UTC
[mocha-developer] Set the return value to "same as block"
On 7/18/07, James Mead <jamesmead44 at gmail.com> wrote:> I''m a bit confused as to what you are trying to test - there are no expects > or asserts in your examples. Can you give a simple but complete example with > both test and code. In particular, are you trying to test the functionality > of the method or the block?I think he''s trying to test the following type of thing (at least, this is how I read it): # test case method def test_should_offset_each_char_by_one_position scrambler = Scrambler.new File.expects( :open ).with( ''/abc.txt'', ''r'' ).yields( stub( :read => ''abc'' ) ) assert_equal ''bca'', scrambler.offset_read( ''abc.txt'' ) end # Scrambler method def offset_read( path ) File.open( path, ''r'' ) do |f| chars = file.read.to_a ( chars << chars.shift ).to_s end end In other words, if you have an expectation which uses #yields, rather than having to explicitly define the return value, is it possible to have it return the result of the block that was yielded to? Maybe this already works -- I haven''t tried. -- Regards, John Wilger http://johnwilger.com ----------- "Quality means doing it right when no one is looking." ? Henry Ford
Jonathan Leighton
2007-Jul-22 15:26 UTC
[mocha-developer] Set the return value to "same as block"
On Wed, 2007-07-18 at 09:45 +0100, James Mead wrote:> I''m a bit confused as to what you are trying to test - there are no expects > or asserts in your examples. Can you give a simple but complete example with > both test and code. In particular, are you trying to test the functionality > of the method or the block?Basically, I am trying to test that my_method returns the contents of the file. The Kernel#open method will return what its block returns, so when stubbing Kernel#open I am trying to simulate this behaviour. The assertion would be (sorry I missed this out): assert_equal "The file contents", obj.my_method Here''s a complete example: require ''test/unit'' class Foo def return_from_block return yield end def my_method return_from_block { "Something" } end end class FooTest < Test::Unit::Testcase def test_my_method foo = Foo.new foo.stubs(:return_from_block).returns(from_block) assert_equal "Something", foo.my_method end end -- Jonathan Leighton, Web Developer http://jonathanleighton.com/
James Mead
2007-Jul-22 17:12 UTC
[mocha-developer] Set the return value to "same as block"
Thanks for taking the time to explain more fully. We know that there are shortcomings in Mocha regarding blocks. It looks to me like you are trying to find a way to indirectly test the code in the block. While I can see how your solution works in some cases, I''m not sure it is a generic solution e.g. what if a method accepts multiple blocks or what if the result of the block is not normally returned by the method being mocked. One thing I''ve been planning on doing for a while is to provide a way to use a new parameter matcher that can check for a block being passed to a mocked method. I think it would have to work by comparing an expected result with the result of executing the block. I have to admit to being a bit undecided about all of this. I think one thing I need to do is to write up a series of scenarios that we need to handle. Let me know if I''ve misunderstood or if you''ve got any other ideas how to make the handling of blocks more straightforward. -- James. http://blog.floehopper.org