Dependency Injection And Javascript

As we move towards a more unit tested and designed approach to our javascript code we’ve been playing with the notion of using dependency injection to allow us to abstract and allow mocking of javascript AJAX server calls. What we’ve done is create a javascript object that handles making AJAX server calls. The AJAX server call object has one method that takes a url, data to post, a success function handler, and an error function handler.

[javascript]
//definition of our real AJAX Server Caller
function AJAXServerCaller()
{
//this created public method that can be called by our code
this.MakeServerCall = function(url, data, successHandler, errorHandler)
{
var dataCleaned = JSON.stringify(data);
$.ajax({
type: "POST",
url: url,
data: dataCleaned,
contentType: "application/json; charset=utf-8",
dataType: "json",
success: successHandler(result.d),
error:function (xhr, ajaxOptions, thrownError){
if(errorHandler != null)
errorHandler(thrownError);
else
alert(‘An Error Has Occurred’);
}
});

}

}
[/javascript]

We house our server caller object in a AJAXServerCaller.js file, and this file is included when any calls are made that use the object to make an AJAX server call in their javascript. In order to make an AJAX Server call an instance of the AJAX server calling object is passed in to a method as a parameter.
[javascript]
//example usage of ajax server caller

//function to handle successful return of AJAX call
function UpdateCustomerSaved(serverData)
{
///…do something to UI after ajax call completes successfully

}

//function to handle error result of AJAX call
function DisplayErrorCustomerSave(errorData)
{
///…do something to UI to notify of error
}

function SaveCustomerData(customerData, ajaxServerCaller)
{
//acutual AJAX processing handed off to our server caller object
ajaxServerCaller.MakeServerCall(‘http://portal/customerSave.aspx?SaveCustomer’, customerData, UpdateCustomerSaved, DisplayErrorCustomerSave);
}

///Click Handler calls save method, creates and passes in server caller instance
function CustomerSaveClickHandler(event)
{
var data = GetCustomerData();
SaveCustomerData(data, new AJAXServerCaller());
}
[/javascript]

When we’re testing any javascript that uses our AJAX server call object we simply include a file called ‘AJAXServerCallerMock.js’ that has an object that has the exact same signature as our real AJAX server calling object, but has an extra property for fake data to be returned by a service call. When testing the instance that is created is now of our mock AJAX server caller and javascript logic that relies on server calls can now be tested without actually hitting a server.

[javascript]
//definition of our mock AJAX Server Caller, must have same object name and
//also the MakeServerCall method defined to act in place of real object
function AJAXServerCaller()
{
//properties to hold fake data to return
//and indexes so can do multiple calls in one test
this.SuccessResultDataArray = new Array();
var usedMockSuccessResultIndex = 0;

//we’ll allow an error to be programmed on a specific call
this.ErrorOnCall = 0;
this.ErrorResultData = null;
var totalCallCount = 0;

//this created public method will fake real server call, pass back preprogrammed data.
this.MakeServerCall = function(url, data, successHandler, errorHandler)
{
totalCallCount++;
// act as if error returned if programmed to do so
if(this.ErrorOnCall == totalCallCount)
{
if(this.SuccessResultDataArray.length<=usedMockSuccessResultIndex)
{
errorHandler(this.ErrorResultData);
}
}
//call success method with data matched to index of call
//and increment method call index.
else
{
if(this.SuccessResultDataArray.length<=usedMockSuccessResultIndex)
{
successHandler(this.SuccessResultDataArray[usedMockSuccessResultIndex]);
usedMockSuccessResultIndex++;
}
else
{
throw ‘no success data available at index:’ + usedMockSuccessResultIndex;
}

}
});

}

}
[/javascript]

One issue with our approach is that our mock AJAX server call in testing is not exactly like the real AJAX call would be since the mock object is not asynchronous. Our mock caller simply fires the functions passed to handle the ajax server result with the programmed mocked return data. This hasn’t been a large issue, but might be problematic down the line. Another issue could also arise if we need to support complex return scenarios with our mock, like multiple return values, or checking the number of calls made. We will have to build a more complicated mock AJAX caller if we run into situations that require more complex mock object programming.

[javascript]
//example testing using QUnit taking advantage of ajax server caller

var glbSuccess = false;

//function to handle successful return of AJAX call
function UpdateCustomerSaved(serverData)
{
glbSuccess = true;

}

test("Test Save Customer Data calls server", function() {

// — if AJAXServerCallerMock.js is included for test this should be our mock
var ajaxCaller = new AJAXServerCaller();

//– program mock return value for one expected call
ajaxCaller.SuccessResultDataArray[0] = "{result:0}";

//–Act
SaveCustomerData(data, ajaxCaller);

//–Assert – check everything ok with ui.
ok(methodToCheckCustomerInGoodState());
});

[/javascript]

Between unit testing and adding dependency injection into our javascript it’s already beginning to look and feel a lot more organized. My hope is this will allow us to produce higher quality javascript code, in less overall time. We shall see!

I Think I Applied SRP Today?

I came across batch job code similar to the below ( the below is just for an example and far simpler than reality!)  that was written to update orders in a database from an xml response from a payment system.  The code should do the following:

  1. Load the response into an object we can read the data from.
  2. Get a list of ‘batches’ returned in the data.
  3. Update the batches as received in our database.
  4. Get a list of orders for each batch and update them accordingly in our database.
Original Code
Original Code

The original code does what it’s supposed to do but I wished to put unit tests around it.  What I found was it was difficult to do because the entry point for my mocks was at the highest level.  The class was also doing three things, getting and parsing the payment response, updating a batch in our system and updating orders in our system.    If I wasn’t careful tests I wrote to tests that orders are updated correctly could break because of changes to how batches are updated, not good. Continue reading “I Think I Applied SRP Today?”

Mocking Closed Objects

Recently I ran across a situation where I was using an object from a third party ORM tool that I wanted to mock for unit testing.  The method I wanted to test uses this particular third party object and calls methods on it that interact with our data store.   I just wanted to test my method and ensure it calls this third party object correctly, I don’t want the third party object to actually be called since it would then attempt to do its business of communicating with the application’s data store.  The problem was that the object does not implement any interface I can use to easily mock it through a mocking facility such as rhino mock.  Some mock facilities, such as rhino mock, will let you mock an actual object if the methods you want to call are virtual and can be overridden.  Unfortunately the methods I was interested in aren’t virtual so can’t extend the object and create a child class mock without having the real base methods fire.  This wouldn’t work since it was just those methods I wanted to fake.

I think I came up with a fairly slick solution, and a friend even told me this is the same solution proposed by Robert Martin in his book ‘Working With Legacy Code’, when encountering this situation.   All the classes and code below are only examples, they aren’t the code I was actually working on, there would be too much to explain if I tried to actually use that!

MockClosedClass

The class I want to mock is named ‘UnitOfWork’.  In order to create a type I can use for abstraction I created an interface, ‘IUnitOfWork’ that reflects all the methods in the class that I’m interested in mocking.  Continue reading “Mocking Closed Objects”