Rob Sanheim
2007-Sep-05 19:32 UTC
[mocha-developer] how to test timeouts? that #returns deprecation again...
I''m writing quite a few specs lately that use Ruby''s Timeout::timeout functionality, making sure that timeout errors are properly handled and everything flows right when some command line tools timeout. I like being able to use Mocha''s #returns right now to force a method to raise a TimeoutError, but I know that usage is going away at some point. I''d like to throw out the code and see if anyone has a better way to test this with Mocha (or otherwise). Here is some simplified code showing the example: class FileSpace < ActiveRecord::Base def dsmc # remove command line wrapper object - this is basically a call that _could_ stall out end def self.query_backup_timeout 15.seconds end # query backup may hang things, so we have to wrap it in a timeout def query_backup_from_tsm Timeout::timeout(self.class.query_backup_timeout) do dsmc.parse_query_backup(dsmc.query_backup) end end end the corresponding spec: describe "File Space" do it "should raise a time out error if query backup takes too long" do FileSpace.expects(:query_backup_timeout).returns(0.1) # make timeout very short file_space = FileSpace.new # force the parse_query_backup method to sleep for 10 seconds, therefore making the timeout happen file_space.dsmc.expects(:parse_query_backup).returns(lambda{ sleep(10) } ) e = lambda { file_space.query_backup_from_tsm }.should.raise(Timeout::Error) end end Again, this is the simplest case -- in more complex examples I have specs making sure that the timeout error is logged, and that the error state gets saved to the database accordingly in the rescue clause. In other cases we used modules in our tests to override the real implementation in the singleton class (by doing dsmc.extend(TimeoutModule) for example), but thats a bit ugly and tiresome. Does anyone see a better way to do this? I really just want to say "I don''t care what this method normally does, just pretend that in this spec it takes n seconds long to complete to force a TimeoutError. thanks, Rob -- http://robsanheim.com
Duncan Beevers
2007-Sep-05 22:03 UTC
[mocha-developer] how to test timeouts? that #returns deprecation again...
Would it be acceptable to just have the potentially long-running method raise the Timeout::Error itself and allow the error to percolate up out of Timeout::timeout? file_space.dsmc.expects(:query_backup).raises(Timeout::Error, ''took too long'')
James Mead
2008-Mar-28 16:13 UTC
[mocha-developer] how to test timeouts? that #returns deprecation again...
I just found this old reply sitting in my drafts folder. I don''t know if it''s any use, but... Hmm. I don''t like having multiple threads knocking around in my unit tests> (see http://www.jmock.org/threads.html - although its examples are in > Java, don''t be put off - they are very readable). > > In this case you are really testing two things - firstly that you are > wrapping the call with a timeout and secondly that the timeout is working > correctly. I would suggest that the second issue is testing third party code > that you should be able to rely on (and ideally should have its own tests). > So in order to test the first issue, you could set up an expectation for the > call to Timeout::timeout. Unfortunately there isn''t currently a nice way to > check that you are passing in the correct block to the timeout method. > > I''m going to mention this to James Adam (one of the other developers at > Reevoo) who ran into a similar issue a while ago - he might be able to help. > -- > James. > http://blog.floehopper.org > http://tumble.floehopper.org >