title: Using a custom stream wrapper as test stub for PHP's http:// stream wrapper
body: <p>I'm writing a custom stream wrapper to use as a stub in unit tests for an HTTP client class that uses the built-in <code>http://</code> stream wrapper.</p>
  
  <p>Specifically, I need control over the value returned in the <code>'wrapper_data'</code> key by calls to <code>stream_get_meta_data</code> on streams created by the custom stream wrapper. Unfortunately, the documentation on custom stream wrappers is woeful and the API seems unintuitive.</p>
  
  <p>What method in a custom wrapper controls the the meta <code>wrapper_data</code> response?</p>
  
  <p>Using the class at the bottom I've only been able to get the following result when I <code>var_dump(stream_get_meta_data($stream));</code> on streams created with the custom wrapper ...</p>
  
  <pre><code>array(10) {
    'wrapper_data' =&gt;
    class CustomHttpStreamWrapper#5 (3) {
      public $context =&gt;
      resource(13) of type (stream-context)
      public $position =&gt;
      int(0)
      public $bodyData =&gt;
      string(14) "test body data"
    }
    ...
  </code></pre>
  
  <p>But I need to coax the wrapper into yielding something like the following on meta data retrieval so I can test the client class's parsing of the data returned by the real <code>http://</code> stream wrapper ...</p>
  
  <pre><code>array(10) {
    'wrapper_data' =&gt; Array(
         [0] =&gt; HTTP/1.1 200 OK
         [1] =&gt; Content-Length: 438
     )
     ...
  </code></pre>
  
  <p>Here's the code I have currently for the custom wrapper:</p>
  
  <pre><code>class CustomHttpStreamWrapper {
  
      public $context;
      public $position = 0;
      public $bodyData = 'test body data';
  
      public function stream_open($path, $mode, $options, &amp;$opened_path) {
          return true;
      }
  
      public function stream_read($count) {
          $this-&gt;position += strlen($this-&gt;bodyData);
          if ($this-&gt;position &gt; strlen($this-&gt;bodyData)) {
              return false;
          }
          return $this-&gt;bodyData;
      }
  
      public function stream_eof() {
          return $this-&gt;position &gt;= strlen($this-&gt;bodyData);
      }
  
      public function stream_stat() {
          return array('wrapper_data' =&gt; array('test'));
      }
  
      public function stream_tell() {
          return $this-&gt;position;
      }
  }
  </code></pre>