Unit Testing — When You Know You Need It But Struggle To Ramp Up

Today I’d like to take some time to think about Unit testing. Something that conceptually excited me when I initially learned about it, but when implementing I found myself struggling to stay afloat. I primarily struggled due to the vast number of tools available, a lack of clear beginner’s ready documentation, and deadlines that needed to be met that pushed researching my roadblocks with testing to the side.

I will be discussing my attempts to circumvent issues I ran into, as well as how I am handling testing at this stage of my dev process. Note: I am currently using Backbone and React as a hybrid MVC, and testing is being handled primarily with Chai/Mocha via the console.

My biggest roadblock, which ended up having the simplest solution: Checking browser storage data on page load. In an effort to improve UI flow, I stored user-token’s in localStorage. Storing the data after the initial token was sent back wasn’t an issue, but my Backbone Model’s initialization threw in the wrench.

if (window.localStorage['user-token']) {
// set data to model for this session
}

The struggle began. The errors I was getting from the console when running the tests were evident. “window.localStorage not defined”. But WHY? I had defined my Globals in a setup file like so many blogs said to (the setup file was previously linked and confirmed good-to-go):

global.document = jsdom.jsdom('<!doctype html><html><body></body></html>');
global.window = document.defaultView;
global.navigator = {userAgent: 'node.js'};

I had the basic parts I needed, and wasn’t running into any issues with testing my React components. So first things first I tried to redefine my Backbone initialize() function that was making the first pass at localStorage. It didn’t really include anything else I needed to test, so I simply tried to redefine it in my testing file as a null function. Nope. No luck. Back to the drawing board.

Second attempt was to comment out that function from the code while testing, so that the source of the error “did not exist”. I did that once, but consistently editing finished code gave me nightmares and I woke up in the middle of the night one night and made a pact not to do something so pointless. I had even made the decision to ignore the testing file, to just make the problem invisible, but I knew I wouldn’t let that settle for long.

At this point I started to give up. I knew where the problem was coming from, I believed I had solved the issue with the global’s my console based tester needed, and I allotted myself 1.5 hours a day to continue researching the matter because I wasn’t going to believe that I was the first person to run into this issue. (The lack of clear answer’s online didn’t seem to match my belief though.) Starting my next project, without the deadlines imposed by school, I re-centered myself and re-iterated my goal to code with the TDD flow rather than letting myself just catch up on testing later.

Eureka, I came back to my beginner’s mind philosophy, starting to think through the simplest form of data I had in front of me. Had I not spent enough time checking how my global variable’s were coercing? I surely had not. Then I saw the light at the end of the tunnel. I had defined my global window, but in doing so I had assumed that window.localStorage came along with that (why was I making magical assumptions).

// the global.window variable checked out fine
global.window = document.defaultView;

// how can I confirm that my assumption was incorrect and that global.window does not immediately include global.window.localStorage?
Why not start by just a simple variable definition?global.window.localStorage;

So I started to test my hypothesis about the window global, with small adaptations to the code rather than spending hours online to research what was included in document.defaultView. I reran my tests with my localStorage global now included. No luck. Ah yes, the localStorage needed to be an object, similar to what my Backbone model was expecting. Another simple addition was made:

global.window.localStorage = { 'user-token': 'test' };

Rerunning my test, the error went away and all my tests passed! Thank. Jeebus. It was a lot of work to get around something that was only being used for my async requests on this Model, but leaving it incomplete and avoiding trying to find a solution just wasn’t going to cut it. I still wanted to be able to verify user input data for the correct formats for logins/registration/etc…

Overall this very small detail put a giant hurdle in front of me. Though this struggle proved to me that I could conceptually tackle these issues if I stepped back from them and worked through them piece-meal. It can be so easy to just hop online and go down a wormhole of possible solutions, but at the end of the day the true’s and false’s are in the code and with some finagling they can be solved. I was happy to mark this bug as fixed.

Now back to the struggle of learning to test async requests being handled with Axiom. *runs and hides*