title: How can I appropriately mock out a method that returns yield?
body: <p>It's fairly common in Ruby for methods that take blocks to look like this:</p>
  
  <pre><code>class File
    def open(path, mode)
      perform_some_setup
      yield
    ensure
      do_some_teardown
    end
  end
  </code></pre>
  
  <p>It's also fairly idiomatic for a method to look like this:</p>
  
  <pre><code>def frobnicate
    File.open('/path/to/something', 'r') do |f|
      f.grep(/foo/).first
    end
  end
  </code></pre>
  
  <p>I want to write a spec for this that doesn't hit the filesystem, which ensures it pulls the right word out of the file, something like:</p>
  
  <pre><code>describe 'frobnicate' do
    it 'returns the first line containing the substring foo' do
      File.expects(:open).yields(StringIO.new(&lt;&lt;EOF))
        not this line
        foo bar baz
        not this line either
      EOF
      expect(frobnicate).to match(/foo bar baz/)  
    end
  end
  </code></pre>
  
  <p>The problem here is that, by mocking out the call to <code>File.open</code>, I've also removed its return value, which means that <code>frobnicate</code> will return <code>nil</code>. If I were to add something like <code>File.returns('foo bar baz')</code> to the chain, however, I'd end up with a test that doesn't actually hit any of the code I'm interested in; the contents of the block in <code>frobnicate</code> could do anything and the test would still pass.</p>
  
  <p>How might I appropriately test my <code>frobnicate</code> method without hitting the filesystem? I'm not particularly attached to any particular testing framework, so if your answer is "use this awesome gem that'll do it for you" then I'm OK with that.</p>