title: Python testing: using a fake file with mock & io.StringIO
body: <p>I'm trying to test some code that operates on a file, and I can't seem to get my head around how to replace using a real file with <code>mock</code> and <code>io.StringIO</code>
  My code is pretty much the following:</p>
  
  <pre><code>class CheckConfig(object):
      def __init__(self, config):
          self.config = self._check_input_data(config)
  
      def _check_input_data(self, data):
          if isinstance(data, list):
              return self._parse(data)
          elif os.path.isfile(data):
              with open(data) as f:
                  return self._parse(f.readlines())
  
      def _parse(self, data):
          return data
  </code></pre>
  
  <p>I have a class that can take either a list or a file, if it's a file it opens it and extracts the contents into a list, and then does what it needs to do to the resulting list. </p>
  
  <p>I have a working test as follows:</p>
  
  <pre><code>def test_CheckConfig_with_file():
      config = 'config.txt'
      expected = parsed_file_data
      actual = CheckConfig(config).config
      assert expected == actual
  </code></pre>
  
  <p>I want to replace the call to the filesystem. I have tried replacing the file with <code>io.StringIO</code> but I get a <code>TypeError</code> from <code>os.path.isfile()</code> as it's expecting either a string, bytes or int. I also tried mocking the <code>isfile</code> method like so:</p>
  
  <pre><code>@mock.patch('mymodule.os.path')
  def test_CheckConfig_with_file(mock_path):
      mock_path.isfile.return_value = True
      config = io.StringIO('data')
      expected = parsed_file_data
      actual = CheckConfig(config).config
      assert expected == actual
  </code></pre>
  
  <p>but I still get the same <code>TypeError</code> as the <code>_io.StringIO</code> type is causing the exception before <code>isfile</code> gets a chance to return something.</p>
  
  <p>How can I get <code>os.path.isfile</code> to return True, when I pass it a fake file? Or is this a suggestion I should change my code?</p>