title: Why does Ruby open-uri's open return a StringIO in my unit test, but a FileIO in my controller?
body: <p>I inherited a Rails 2.2.2 app that stores user-uploaded images on Amazon S3. The attachment_fu-based <code>Photo</code> model offers a <code>rotate</code> method that uses <code>open-uri</code> to retrieve the image from S3 and MiniMagick to perform the rotation. </p>
  
  <p>The <code>rotate</code> method contains this line to retrieve the image for use with MiniMagick:</p>
  
  <pre><code>temp_image = MiniMagick::Image.from_file(open(self.public_filename).path)
  </code></pre>
  
  <p><code>self.public_filename</code> returns something like </p>
  
  <pre><code>http://s3.amazonaws.com/bucketname/photos/98/photo.jpg
  </code></pre>
  
  <p>Retrieving the image and rotating it work just fine in the running application in production and development. However, the unit test fails with</p>
  
  <pre><code>TypeError: can't convert nil into String
      /Users/santry/Development/totspot/vendor/gems/mini_magick-1.2.3/lib/mini_magick.rb:34:in `initialize'
      /Users/santry/Development/totspot/vendor/gems/mini_magick-1.2.3/lib/mini_magick.rb:34:in `open'
      /Users/santry/Development/totspot/vendor/gems/mini_magick-1.2.3/lib/mini_magick.rb:34:in `from_file'
  </code></pre>
  
  <p>The reason is that when the model method is called in the context of the unit test, <code>open(self.public_filename)</code> is returning a <code>StringIO</code> object that contains the image data. The <code>path</code> method on this object returns <code>nil</code> and <code>MiniMagick::Image.from_file</code> blows up.</p>
  
  <p>When this very same model method is called from the <code>PhotosController</code>, <code>open(self.public_filename)</code> returns a <code>FileIO</code> instance tied to a file named, eg, <code>/tmp/open-uri7378-0</code> and the file contains the image data.</p>
  
  <p>Thinking the cause must be some environmental difference between test and development, I fired up the console under the development environment. But just as in the unit test, <code>open('http://...')</code> returned a <code>StringIO</code>, <em>not</em> a <code>FileIO</code>.</p>
  
  <p>I've traced my way through open-uri and all the relevant application-specific code and can find no reason for the difference.</p>