Jim Lynch Codes
  • Blog
  • About Jim

Writings about one coder's stories & experiences.

Spying on Methods of Object Under Test Vs. Spying on Methods of It's Dependencies (in AngularJS)

8/17/2016

0 Comments

 
In this post I quickly want to go over the difference between using spyOn for methods of the object under tests and using spyOn to spy on methods of an object that is a dependency of the object under test. This is another post that's all about "testing one thing at a time" in your AngularJS unit tests by "using the real thing" for the object or method under test and using spyOn to fake rest. 
Use the real thing for the object / method under test,
        and use spyOn to fake rest.

Make a New Unit Test File

Sanity check- here's where we're starting. This is a file containing an empty suit of unit tests which just sets up out Angular module and injects one service, ScrollCalulator. I'm still using Es5 JavaScript, but the main ideas will apply for really any language.  
(function() {
  'use strict';

  describe('controllers', function(){
    var AgendaAutoScroller;

    beforeEach(module('agendaIpad'))
    beforeEach(inject(function(_AgendaAutoScroller_) {
      AgendaAutoScroller = _AgendaAutoScroller_;

      });
    })





  });

})();

Using spyOn To Make Fake Implementations for Methods on the Object Under Test

Suppose we're testing the "calculateScrollAmount" method, but for some reason we want to define a fake implementation for "getContainerHeight" so that it just automatically returns 500. In this code snippet below I'm spying on getContainerHeight, another method in AgendaAutoScroller and defining a fake implementation for it that just returns 500. The point of doing this is that the calculateScroll method calls 'getContainerHeight' at some point when it's invoked so in order for the assertion that calls "calculateScroll" you need to have getContainerHeight returning something valid (like 500). 
(function() {
  'use strict';

  describe('AgendaAutoScroller', function(){
    var AgendaAutoScroller;

    beforeEach(module('agendaIpad'))
    beforeEach(inject(function(_AgendaAutoScroller_) {
      AgendaAutoScroller = _AgendaAutoScroller_;

      spyOn(AgendaAutoScroller,['getContainerHeight']).and.callFake(function () {
        return 500;
      });

      });
    })


    it('should calculate 800 when I enter 400', function () {
        
      expect(AgendaAutoScroller.calculateScroll(400)).toEqual(800);

    });



  });

})();

Using spyOn for Methods of Dependency Objects

You can also spyOn methods that are calling from dependencies within the function you are trying to test. Suppose the instead of 'getContainerHeight' being a method on AgendaAutoScroller, it's instead a method of a different AngularJS "service service", let's call this new one HeightTracker. So in our AgendaAutoScroller service when it's created we inject HeightTracker, and we later call HeightTracker.getcontainerHeight() from inside of AgendaAutoScroller.calculateScroll().
So in our unit test we can inject this dependency, and just spy on it's methods. Because they are the exact same name, Angular knows to use this "spied on" version of the HeightTracker dependency when creating AgendaAutoScroller.
(function() {
  'use strict';

  describe('AgendaAutoScroller', function(){
    var AgendaAutoScroller;
    var HeightTracker;

    beforeEach(module('agendaIpad'))
    beforeEach(inject(function(_AgendaAutoScroller_), _HeightTracker_ {
      AgendaAutoScroller = _AgendaAutoScroller_;
      HeightTracker = _HeightTracker_;

      spyOn(HeightTracker,['getContainerHeight']).and.callFake(function () {
        return 500;
      });

      });
    })


    it('should calculate 800 when I enter 400', function () {
        
      expect(AgendaAutoScroller.calculateScroll(400)).toEqual(800);

    });



  });

})();

Bonus Tip: "Spy on" Variables 

The actual Jasmine method spyOn won't work for variables, but in therms of being able to create your own fake implementation / value for unit tests in the same section of your file when you would spyOn your methods you can just manually set variables of either your object under test or any dependencies simply by injecting them and setting the values. In the example below, when AgendaAutoScroller is created and has HeightTracker injected into it the value of HeightTracker.initialValue is true.
(function() {
  'use strict';

  describe('AgendaAutoScroller', function(){
    var AgendaAutoScroller;
    var HeightTracker;

    beforeEach(module('agendaIpad'))
    beforeEach(inject(function(_AgendaAutoScroller_), _HeightTracker_ {
      AgendaAutoScroller = _AgendaAutoScroller_;
      HeightTracker = _HeightTracker_;

      HeightTracker.initialValue = true;

      });
    })


    it('should calculate 800 when I enter 400', function () {
        
      expect(AgendaAutoScroller.calculateScroll(400)).toEqual(800);

    });



  });

})();
0 Comments

Your comment will be posted after it is approved.


Leave a Reply.

    ​Author

    Picture
    The posts on this site are written and maintained by Jim Lynch. About Jim...
    Picture
    Follow @JimLynchCodes
    Follow @JimLynchCodes

    Categories

    All
    Actionscript 3
    Angular
    AngularJS
    Automated Testing
    AWS Lambda
    Behavior Driven Development
    Blockchain
    Blogging
    Business Building
    C#
    C / C++
    ClojureScript / Clojure
    Coding
    Community Service
    CS Philosophy
    Css / Scss
    Dev Ops
    Firebase
    Fitness
    Flash
    Front End
    Functional Programming
    Git
    Go Lang
    Haskell
    Illustrations
    Investing
    Java
    Javascript
    Lean
    Life
    Linux
    Logic Pro
    Music
    Node.js
    Planning
    Productivity
    Professionalism
    Python
    React
    Redux / Ngrx
    Refactoring
    Reusable Components
    Rust
    Security
    Serverless
    Shell Scripting
    Swift
    Test Driven Development
    Things
    TypeScript
    Useful Sites
    Useful Tools
    Video
    Website Development
    WebStorm
    Writing

    Archives

    March 2023
    August 2021
    February 2021
    January 2021
    October 2020
    September 2020
    May 2020
    April 2020
    February 2020
    January 2020
    December 2019
    October 2019
    September 2019
    August 2019
    July 2019
    June 2019
    May 2019
    April 2019
    March 2019
    February 2019
    January 2019
    December 2018
    November 2018
    October 2018
    September 2018
    August 2018
    June 2018
    May 2018
    April 2018
    March 2018
    February 2018
    January 2018
    December 2017
    November 2017
    October 2017
    September 2017
    August 2017
    July 2017
    May 2017
    April 2017
    March 2017
    February 2017
    January 2017
    December 2016
    November 2016
    October 2016
    September 2016
    August 2016
    July 2016
    June 2016
    May 2016
    April 2016
    March 2016
    February 2016
    January 2016
    December 2015
    November 2015
    October 2015

    RSS Feed

  • Blog
  • About Jim
JimLynchCodes © 2023