title: Mocking / Fake / Replacing hardware dependent functions in Unit Tests
body: <p>I have currently the following function in one file:</p>
  
  <pre class="lang-go prettyprint-override"><code>func pinExported(pin int) bool {
      pinPath := fmt.Sprintf("/sys/class/gpio/gpio%d", pin)
      if file, err := os.Stat(pinPath); err == nil &amp;&amp; len(file.Name()) &gt; 0 {
          return true
      }
      return false
  }
  </code></pre>
  
  <p>and another code part in the same file which uses the above function which looks like this:</p>
  
  <pre class="lang-go prettyprint-override"><code>func isGpioPinExported(gpioPin int) bool {
      exported := pinExported(gpioPin)
      for !exported &amp;&amp; (timeOut &lt; timeOutForPinExportInMilliseconds) {
          timeOut++
          time.Sleep(1 * time.Millisecond)
          exported = pinExported(gpioPin)
      }
       ...
  </code></pre>
  
  <p>So now I'm searching for an elegant way to mock/replace somehow the above <code>pinExported</code> function within my unit tests to test the logic inside <code>isGpioPinExported</code> because the function <code>pinExported</code> is hardware dependent (Raspberry PI).</p>
  
  <p>One solution could be to make the <code>pinExported</code> function a parameter of <code>isGpioPinExported</code></p>
  
  <p>So defining a function type like this:</p>
  
  <pre><code>type pinExported func(int) int
  </code></pre>
  
  <p>which means I have to define <code>isGpioPinExported</code> like this:</p>
  
  <pre><code>isGpioPinExported(pinExported pinExported, gpioPin int) bool {
      exported := pinExported(gpioPin)
      for !exported &amp;&amp; (timeOut &lt; timeOutForPinExportInMilliseconds) {
      ...
      }
      ..
  }
  </code></pre>
  
  <p>Now I can write my unit test and define a mock/fake <code>pinExported</code> without a problem. So far so good. But I have about five or six of such functions which means it would result in putting five or six supplemental parameters to a function like <code>isGpioPinExported</code> which is simply wrong. Apart from that the question is where can I define the default implementation which are used if this is not running under test?</p>