title: Stubbing and/or spying on an optional global function: Sinon, mocha & chai
body: <p>I have a method that checks whether or not a global function is defined (it may or may not be available, depends on each client's request).  If it is defined, it will call it with the appropriate data. If not, it will fail silently. That's the desired behavior.</p>
  
  <p>What I want to do is test it. Is there a way to mock and/or spy on <code>libFunction</code> so that I can ensure it's being called once with the correct data (the function here is very much simplified, there's some data processing that happens along the way).</p>
  
  <p>Here's the method in question:</p>
  
  <pre><code>function sendData(data) {
    let exists;
    try {
      // eslint-disable-next-line no-undef
      if (libFunction) exists = true;
    } catch (e) {
      exists = false;
    }
    if (exists) {
      // eslint-disable-next-line no-undef
      libFunction(data);
    }
  }
  </code></pre>
  
  <p>I've tried defining <code>libFunction</code> in my tests and then stubbing that, but that doesn't do what I want:</p>
  
  <pre><code>describe('sendEvent', function () {
  
    function libFunction(data) {
      console.log('hi', data);
    }
  
    it('should call libFunction once', function () {
      var stub = sinon.stub(libFunction);
      var data = "testing";
      sendEvent(data);
      expect(stub.called).to.be.true;
    });
  });
  </code></pre>
  
  <p>This test does not pass, however: <code>AssertionError: expected undefined to be true</code></p>
  
  <p>I've tried something similar with a spy:</p>
  
  <pre><code>describe('sendEvent', function () {
  
    function libFunction(data) {
      console.log('hi', data);
    }
  
    it('should call libFunction once', function () {
      var spy = sinon.spy(libFunction);
      var data = "testing";
      sendEvent(data);
      expect(spy.called).to.be.true;
    });
  });
  </code></pre>
  
  <p>This also fails: <code>AssertionError: expected false to be true</code></p>
  
  <p>Is there a way to do this?</p>