We all know that SalesForce enforces a 75% code coverage rule for code in production and whilst it can be a pain having this pushed down on us it’s also a great thing. A great thing, that is, so long as we write good tests, assert sensible conditions and as a consequence achieve fantastic code coverage; not acheive the minimum code coverage, assert random things and write tests as an after thought. But for the purpose of this discussion let’s assume that we’re all writing good test for the right reasons. Even when we do acheive these things I think that the platform itself hinders us from achieving better test coverage and cleaner code by forcing us into a tightly coupled design.

I’m sure that we can all agree that a decoupled design is a good design and so long as it’s done well it can be benifical in terms of development, readability, maintence and testability. And we all also know that the OO construct at the centre of loose coupling is the interface. It’s a much unsung construct within Salesforce with the only real references to it being in terms of the Batchable and Schedulable interfaces. Other than that interfaces don’t really crop up too much.

To me these two things seem to contradict each other: the need for good test coverage and the lack of exposed interfaces in the code. Why? Well, let’s take this somewhat contrived example, it takes a couple of parameters, creates a new Account object and then calls an imaginative ReST service which takes a date a returns the sign of the zodiac that it relates to (please don’t ask me how I came up with this example!). The service returns text in the body, if there’s an error the word BAD is returned, if successful the name of the zodiac sign is returned. This is the very unimaginative code which probably isn’t as robust as it should be – but it’s an example…

public class ExampleClass{
  public void CreateAnAccount(String accountName, Date DOB){
    Account a = new Account(name = accountName, DateOfBirth = DOB);
    Http h = new Http();
    HttpRequest req = new HttpRequest();
    req.setEndpoint('http://zodiacsrus.com/whichzodiac/' + string.valueOf(DOB));
    req.setMethod('GET');
    HttpResponse res = h.send(req);
    String result = res.getBody();

    if(result == 'BAD')
      throw new MagicException('Something really bad happened.');

    a.star_sign__c = result;
    insert a;
  }
}

So, looking at that example we see that it’s actually impossible to test in the state that it is currently in. In this example that’s not too much of an issue but if this method was more complex we would definitley need a robust test suite around it.

So, how do we approach making this testable. Well Salesforce does provide us with a solution in the form of the Test.isRunningTest method. We can make use of this method to allow us to not make the callout and instead return some dummy data. On the face of it this sounds like it would be ideal and should provide a way of achieving a much better test solution. However it too comes with its own set of issues; take a look at the adapted code below…

public class ExampleClass{
  public void CreateAnAccount(String accountName, Date DOB){
    Account a = new Account(name = accountName, DateOfBirth = DOB);
    Http h = new Http();
    HttpRequest req = new HttpRequest();
    req.setEndpoint('http://zodiacsrus.com/whichzodiac/' + string.valueOf(DOB));
    req.setMethod('GET');

String result;
    if(!Test.isRunningTest){
      HttpResponse res = h.send(req);
      result = res.getBody();
    } else{
      result = 'BAD';
    }

    if(result == 'BAD')
      throw new MagicException('Something really bad happened.');

    a.star_sign__c = result;
    insert a;
  }
}

As you can see now we have a different issue; there are two parts of this method that will never be tested. There’s the HTTP callout, which we accept isn’t possible to test. The other is the last two lines where we assign the value to our custom field and insret the record. This is because the dummy data that we create contains an erronous response code and hence the succesful path won’t be tested. Simply changing the response to be a ‘positive’ response won’t really solve the issue either as then the exception handling path won’t be exercised during testing either. The problem is that we can only ever have one type of dummy return; which in turn means that we can only test one code path after the return. On top of this we start to pollute our true business logic with test code, which can quickly become messy and unmaintainable.

So, is there another solution? Well, unsurprisingly there is or at least there could have been if Salesforce had exposed an interface to the Http object. I know; it sounds convincing but how would it have worked? Well, to show you let’s extend our simple example to make use of such an interface and to keep it simple I’m not going to worry too much about the implementation and the need for other interfaces. The first job is to declare the interface, I’m going to call it IHttp as Salesforce doesn’t have a clear guide on naming interfaces and I like the I notation as I come from a C# background.

global interface IHttp{
  HttpResponse send(HttpRequest req);
}

We can now add a public IHttp field to our class containing the CreateAnAccount method and use that IHttp instance in our CreateAnAccount like so.

public class ExampleClass{
  public IHttp httpInstance;

  public void CreateAnAccount(String accountName, Date DOB){
    Account a = new Account(name = accountName, DateOfBirth__c = DOB);

    HttpRequest req = new HttpRequest();
    req.setEndpoint('http://zodiacsrus.com/whichzodiac/' + string.valueOf(DOB));
    req.setMethod('GET');

    String result;
    HttpResponse res = httpInstance.send(req);
    result = res.getBody();

    if(result == 'BAD')
      throw new MagicException('Something really bad happened.');

    a.star_sign__c = result;
    insert a;
  }
}

That looks clean but where does the httpInstance get set? Well it needs to be set before you call CreateAnAccount, this could be shifted into a contructor and the field made private or it could be left as is with the onus on the person using the class to remember to set it. Either way it doesn’t matter right now. What is more important is what does it get set to? And this is where I think the elegance of this whole thing lies, you can choose.

OK, let me explain that a little more if I can. In this example we have assumed that Salesforce have exposed the IHttp interface and as such the Http class that is part of the platform implements that interface. This means that when we’re using this code in production we can set the httpInstance field to jut be a new instance of the standard Http class and everything will continue to function as normal. A call to the CreateAnAccount method would look something like this.

ExampleClass eg = new ExampleClass();
eg.httpInstance = new Http();
eg.CreateAnAccount('Simon', Date.valueOf('1979-09-21'));

OK, so that’s straight forward enough but how does it help me test and more importantly achieve better test coverage? The answer is simple and it lies in creating your own classes that implement the IHttp interface.

Please note that to keep this next piece simple we need to suspend reality just temporarily and imagine that we can instantiate a HttpResponse and in the contructor pass the response. I know that you can’t but it helps with this example.

public class WhichZodiacBadResponse implements IHttp{
  public HttpResponse send(HttpRequest req){
    return new HttpResponse('BAD');
  }
}

public class WhichZodiacGoodResponse implements IHttp{
  public HttpResponse send(HttpRequest req){
    return new HttpResponse('Virgo');
  }
}

@isTest
private class ExampleClassTest{
  private static testMethod void CreateAnAccount_Success{
    ExampleClass eg = new ExampleClass();
    eg.httpInstance = new WhichZodiacGoodResponse();
    eg.CreateAnAccount('Simon', Date.valueOf('1979-09-21'));
  }

  private static testMethod void CreateAnAccount_BadReSTResponse{
    ExampleClass eg = new ExampleClass();
    eg.httpInstance = new WhichZodiacBadResponse();
    eg.CreateAnAccount('Simon', Date.valueOf('1979-09-21'));
  }
}

The structure of the test methods has been overly simplified for the sake of clarity; exceptions need to be caught and assertions need to be made etc. However you should now be able to see that we have in fact been able to test all of the code paths and without cluttering up our code. And all thanks to the senisble use of interfaces which have allowed us to decouple our code.

I’m sure that most of you will recognise what I have described here as dependancy injection and I’m not really spouting anything new what I am trying to say though is that this pattern is a good thing. And it’s good for a multitude of reasons which I’m not going to sit here and regurgitate. What I do want to emphasise though is the lack of use of this pattern within Salesforce; it surprises me that they aren’t providing us with more of a chance to make use of it by making more interfaces available. With Batchable and Schedulable they are clearly doing some form of DI themselves so why not create some more interfaces to the platform and let us make use of them; giving us the chnce to write better tested, clearer code?

And if they wanted to bake a DI framework in there for us as well then that would be great too! By giving us such a framework Salesforce would provide us with the opportunity to write much more decoupled software ourselves, working to our own interfaces and being able to build much more robust and reuseable solutions. This must surely be in everyone’s interest – this allows us to use already tested code to build our solutions andeasily replace broken parts when needed – all of which leads to more maintainable code written faster and with fewer bugs.

I realise that all of this is a long way down most people’s list of wants from the platform and as such we’ll probably never see Salesforce provide us with any more interfaces and the prospect of a DI framework is somewhere out there with me winning the lottery. So, what can be done instead? Well, there nothing stopping us from defining these interfaces ourselves and having one implementation that just calls on down to the standard platform object. All we need is a GitHub project for people to but the interfaces and standard implementations into… and yes, you’ve guessed it that’s what I think I’m going to start over the next week or so – and this time not because I need it but because it’s the right thing to do! As for a DI framework, I have a few ideas tumbling around in my head about that as well at the moment but I think they’re going to take a little longer to become cohesive, so you’ll just have to wait a bit for that one.