<p>I'm a Java-developer toying with Ruby, and loving it. I have understood that because of Ruby's metaprogramming facilities my unit-tests become much cleaner and I don't need nasty mocking frameworks. I have a class which needs the <code>File</code> class's services and in my test I don't want to touch my real filesystem. In Java I would use some virtual file system for easier "seams" to pass fake-objects in but in Ruby that's obviously overkill. What I come up seems already really nice compared to the Java-world. In my class under test I have an optional constructor parameter: </p>

<pre><code>def initialize(file_class=File)
</code></pre>

<p>When I need to open files within my class, I can then do this:</p>

<pre><code>@file_class.open(filename)
</code></pre>

<p>And the call goes to either the real File-class, or in case of my unit-test, it goes to a fake-class which doesn't touch the filesystem. I know there must be a better way to do this with metaprogramming?</p>

[{'answer_id': 72248, 'author': 'Brian Phillips', 'author_id': 7230, 'author_profile': 'https://Stackoverflow.com/users/7230', 'pm_score': 4, 'selected': False, 'text': '<p>Mocha (<a href="http://mocha.rubyforge.org/" rel="noreferrer">http://mocha.rubyforge.org/</a>) is a very good mocking library for ruby.  Depending on what you\'re actually wanting to test (i.e. if you want to just fake out the File.new call to avoid the file system dependency or if you want to verify that the correct arguments are passed into File.new) you could do something like this:</p>\n\n<pre>\n<code>\nrequire \'mocha\'\n\nmock_file_obj = mock("My Mock File") do\n  stubs(:some_instance_method).returns("foo")\nend\n\nFile.stubs(:new).with(is_a(String)).returns(mock_file_obj)\n</code>\n</pre>\n'}, {'answer_id': 73605, 'author': 'tomafro', 'author_id': 7126, 'author_profile': 'https://Stackoverflow.com/users/7126', 'pm_score': 1, 'selected': False, 'text': '<p>In the case you\'ve outlined, I\'d suggest that what you\'re doing seems fine.  I know that it\'s a technique that James Mead (the author of Mocha) has advocated.  There\'s no need to do metaprogramming just for the sake of it.  <a href="http://www.floehopper.org/articles/2007/11/29/mock-object-injection" rel="nofollow noreferrer">Here\'s what James has to say about it</a> (and a long list of other techniques you could try)</p>\n'}, {'answer_id': 17243303, 'author': 'Mulan', 'author_id': 633183, 'author_profile': 'https://Stackoverflow.com/users/633183', 'pm_score': 1, 'selected': False, 'text': '<p>This is a particularly difficult challenge for me. With the help I received on <a href="https://stackoverflow.com/questions/17204371/how-to-test-factory-pattern-using-mocha-in-ruby">this question</a>, and some extra work on my behalf, here\'s the solution I arrived at.</p>\n\n<pre><code># lib/real_thing.rb\nclass RealThing\n  def initialize a, b, c\n    # ...\n  end\nend\n\n# test/test_real_thing.rb\nclass TestRealThing &lt; MiniTest::Unit::TestCase\n\n  class Fake &lt; RealThing; end\n\n  def test_real_thing_initializer\n    fake = mock()\n    Fake.expects(:new).with(1, 2, 3).returns(fake)\n    assert_equal fake, Fake.new(1, 2, 3)\n  end\n\nend\n</code></pre>\n'}]
['https://Stackoverflow.com/questions/72220', 'https://Stackoverflow.com', 'https://Stackoverflow.com/users/4110/']