title: Angular Unit Testing - Mocking methods/closures in same service
body: <p>I'm currently trying to unit test my angular service using <a href="http://sinonjs.org/" rel="nofollow noreferrer">SinonJS</a>, but have been running into an issue and was hoping someone could possibly shed some light on why this is occurring. I have reconstructed my current project to illustrate the problem at hand.</p>
  
  <p>I have also provided a <a href="http://plnkr.co/edit/XG3SLLedDK64Ta9llc7T?p=preview" rel="nofollow noreferrer">DEMO</a> </p>
  
  <p>I have a service, <code>peopleService</code>:</p>
  
  <pre><code>(function (){
  
    angular.module('myApp')
      .factory('peopleService', peopleService);
  
      peopleService.$inject = ['$q'];
  
      function peopleService ($q){
        var people = ['Homer', 'Marge', 'Bart', 'Lisa', 'Maggie'];
  
        // in actual project, this makes an http request
        function getFamily () {
           return people;
        }
  
        function getAdults (){
          var family = getFamily();
          return family.filter(function (person){
            return person === 'Homer' || person === 'Marge';
          });
        }
  
        return {
          getFamily: getFamily,
          getAdults: getAdults
        }
      }
  
  }());
  </code></pre>
  
  <p>In this service, my method <code>getAdults</code> uses <code>getFamily</code>, filters the results, and returns the data.  </p>
  
  <p>In my unit test, I am trying to mock <code>getFamily</code> and see if that method is being called. Now this is where the problem presents itself...</p>
  
  <p>First thing I tried was stubbing out the method and overwriting the current method, like so:</p>
  
  <pre><code>beforeEach(function (){
    module('myApp');
  
    inject(function (_peopleService_){
      peopleService = _peopleService_; // get the service
      sinon.stub(peopleService, 'getFamily'); // stub it
    });
  });
  </code></pre>
  
  <p>I then go to test whether <code>getAdults</code> calls the <code>getFamily</code> method:</p>
  
  <pre><code>it('getAdults should call "getFamily" once', function(){
       peopleService.getAdults();
       expect(peopleService.getFamily.calledOnce).toBe(true);
  });
  </code></pre>
  
  <p>The test fails and the stubbed method is not called...</p>
  
  <p>I debug and find out that although the function has in fact changed:
  <img src="https://i.stack.imgur.com/ENG0t.png" alt="enter image description here"> </p>
  
  <p>The service still holds a reference (closure) to what the method used to be when the service was created:</p>
  
  <p><img src="https://i.stack.imgur.com/SGxJv.png" alt="enter image description here"></p>
  
  <p>My initial thought was I didn't stub the method correctly. I then attempted overwriting the method using <a href="https://docs.angularjs.org/api/auto/service/$provide" rel="nofollow noreferrer"><code>$provide</code></a> (<code>$provide.value</code>) as well as <a href="https://docs.angularjs.org/api/auto/service/$provide#decorator" rel="nofollow noreferrer"><code>$injector decorator</code></a> and I ended up getting the same result (closure held onto the original method). </p>
  
  <p>A solution to this would be to use <code>this</code>: </p>
  
  <pre><code> function getAdults (){
      var family = this.getFamily(); // &lt;-- by using this.getFamily would reference the mock
      return family.filter(function (person){
        return person === 'Homer' || person === 'Marge';
      });
    }
  </code></pre>
  
  <p>However, I do not understand why I have to do this.</p>
  
  <p>In short, does anyone know:</p>
  
  <ul>
  <li>how to mock another method in the same service without having to use <code>this</code></li>
  <li>how to mock out a closure variable in a unit test</li>
  </ul>
  
  <p>Thank you so much for your time.</p>