Mocking fundamentals – simple mocks without frameworks

What you have to know before giving up with mocks

hello-i-m-nik-v8pL84kvTTc-unsplash– Photo by Hello I’m Nik 🇬🇧 on Unsplash

Maybe you have heard about the mocking technique a lot, but never understood very well how it works or doubted if it is really worthwhile. This article is aimed at those who do not know what the tests with mocks are and what they are for. I’ll focus on telling you about the pillars of such technique, why it is good for unit testing and how apply it in your application without the need of a framework.

Then, in a future post, I’ll show you the steps to progressively transition from integration tests to real unit tests and how to adopt the popular ApexMocks framework. That will really make the difference to your daily work. However, you’ll get better results if you first let the mocking principles to mature in your mind. Really exciting, isn’t it?

Before we start let me add a little warning. For simplicity, throughout this article, I have used the term mock or mocking to refer generically to the substitution techniques applied to unit tests. To be more precise, in addition to mocks, I should have been used other terms like Test Doubles and Stubs. But getting to that level of detail could make things explained here more confusing for the less experienced developers, not to say that the literature around there turns a little contradictory sometimes. But once you have become fluent in the technique presented in this article, I recommend you to revisit the terminology. It will be quite revealing and will make you able to have more comprehensive conversations with other devs around the topic.

Why to use mocks?

I like to define it as follows: Mocking is a technique in software development that helps to test well architected applications.

Well, the presence of mocks in the tests of an application doesn’t mean it is well architected. Though, in my experience, the absence of them is a good indicator that probably it is not.

We could say the technique is a starting point for you to craft good architecture, but combining it with others like BDD, really changes the game. But when someone is not versed on these number of topics, aiming to apply the whole theoretical aspects from day one might sound overwhelming. Nevertheless, it is not an “all or none” and one technique will naturally conduce you to the other at some point. This is why, in this post, I will be focused on giving you the tips you need to do mocks and really get their benefits.

So, why should I implement mocks? What are the promised benefits?

Actually there are many, that are even more noticeable in the Salesforce platform. With mocks you can:

  • Reduce the execution time of your tests. Thus, get quicker CI/CD.
  • Decouple unit tests from the implementation of the other classes. Get tests aligned with the Open Closed principle. Test that don’t break easily.
  • Test wider and more complex scenarios.
  • Ensure each layer is independent from the others (SOC).
  • Allow coding real unit tests, not only integration tests.

In summary, you get fast, more reliable and better real unit tests.

About the last point in the list, it is important to note that you’ll still need to create some integration tests. Those will cover the non programatic aspects of your app and ensure your services work well as a whole.

It is easy to give up

But I challenge you to not doing it. Hopefully, after reading this post you’ll feel more engaged to use mocks.

For developers not used use mocks, it is hard to see the aforementioned benefits of that technique at the beginning. They easily get absorbed by an awkward feeling of insecurity and quickly get misguided conclusions:

In this way I’m not really testing my application. I’m actually faking it to ensure it pass through certain lines and if something changes, my tests will break easily.

I was one of those reluctant to change devs several years ago. The truth is that it is hard to change that mindset and use mocks when you have been long time only doing integration tests. Your subconscious tricks you into continuing to see unit tests as a data input-output check in a specific user context or scenario, sometimes driven by the 75% coverage goal. You would feel unsafe from failures otherwise. And that is sometimes closely related with applications with certain lack of separation of concerns which makes mocks to seem even more pointless.

Fortunately I found great mentors during my journey and got understand mocks and see that they are just a part of a whole. An important tool we all must know. But it turns out to be quite complicated to understand at the beginning. Partially because of the huge amount of, sometimes misleading, information one can find nowadays out there one doesn’t know where to start looking at.

Another fact I found that keeps devs away from mocks is the need to build or adopt a mocking framework. I personally found the definition of the StubProvider Interface not very revealing for the ones without previous experience on that topic (e.g. devs with experience in Mockito for Java).

The Wikipedia definition of mock objects is pretty good, but it might sound odd to pure “classic Apex” developers (I’m feeling old now). Remember that many Salesforce Developers first job has been to code in apex which it is hard for them to get influenced by the outside world industry standards. There are good news, though. The mocking technique is sustained by a very simple principle: the ability to replace, at run time, instances of classes (objects) you are not interested in at that moment by others with customised behaviour.

The essentials

Let’s start right by the our last sentence: “mocking is […] the ability to replace […] objects […] by others with customised behaviour”.

So, if you have a function which behaviour depends on other classes, you can simulate (replace) these “external resources”, so that you can test that your method behaves as expected in all kind of scenarios regardless its dependencies. Or said differently: You can test that your method behaves as expected for every single combination of behaviour of your dependencies.

In a nutshell: you can test just your method and ignore the complexities of everything else. Pretty neat and clean.

A lot of wording but no code at all. Show me something now!

You are right. So, lets say we have for instance:

public with sharing class House {
    @IsTestVisible
    private Boolean isDoorOpen = false;

    public void openDoor() {
        SecurityService security = new SecurityService();
        Boolean userHasAccess = security.isCurrentUserAllowedToEnter();

        if (!userHasAccess) {
            throw new SecurityException('You do not have access to this house');
        }

        isDoorOpen = true;
    }
}

If we were to test the openDoor method as it is to ensure all the possible variations of the SecurityService class, we’d need to insert a few records like a user and its permissions, permission set assignments, etc. Then use the runAs method to check it works in all our scenarios. Something like:

@isTest
private class HouseTests {
    @isTest
    private static void openDoor_userHasAccess_doorOpen() {
        // Given
        User userWithAccess = new User(
            FirstName = 'Gregory,
            LastName = 'House',
            //...rest of params);
        insert userWithAccess;

        PermissionSet houseManagementPS =
            [SELECT Id FROM PermissionSet WHERE Name = 'HouseManagement'];
        insert new PermissionSetAssignment(
            AssigneeId = userWithAccess.id,
            PermissionSetId = houseManagementPS.Id);

        // When
        System.runAs(userWithAccess) {
            House standardHouse = new House();
            standardHouse.openDoor();
        }

        // Then
        System.assert(standardHouse.isDoorOpen,
            'The door should be open.');
    }
}

The problematic is obvious here:

  • We need to perform a couple of inserts and a query before testing anything.
  • SecurityService internals will interfere also on the efficiency of the tests.
  • If the SecurityService implementation, we’ll have to amend the HouseTests too!
  • We are coupled to the SecurityService class and our tests must serve the data it consumes to success.
  • isParallel=true is not allowed when the tests refer to the User object. Slower tests.
  • Tests become more verbose deviating the attention from the important (a flag is set to true or not!).
  • If this test doesn’t fail, it doesn’t mean it is correct. If you remove all the SecurityService code from the House class, the test will still work.

It is reasonable to state that the problem will become bigger as the dependent class grows in complexity. Our objective with the mocking technique is to remove all those problems so that we can produce something like:

@isTest(isParallel=true)
private class HouseTests {
    @isTest
    private static void openDoor_userHasAccess_doorOpen() {
        // Given
        makeSecurityToPass();

        // When
        House standardHouse = new House();
        standardHouse.openDoor();

        // Then
        System.assert(standardHouse.isDoorOpen,
            'The door should be open.');
        verifySecurityHasBeenChecked();
    }
}

This sounds kind of obscure magic, but as I promised, it is pretty simple. We just need a way to tell the openDoor method to use a customised version of the SecurityService class. In other words, we have to replace the class instance by its mock.

Ways to replace behaviour

We have listed a number of problems for the HouseTests, but they are actually a consequence of not having the best design for the House class. Think that we cannot use a different security mechanism if we were creating different kind of houses. That is to say that the House class is tightly coupled with the SecurityService class. The secret: we have to remove the new keyword from the House class. Let’s see how.

Setup

Firs of all, we have to make a little tweak to our SecurityService. Pay attention to the highlighted lines below:

public with sharing class SecurityService
    implements ISecurityService {

    public interface ISecurityService {
        Boolean isCurrentUserAllowedToEnter();
    }

    public Boolean isCurrentUserAllowedToEnter() {
        // security stuff here
    }
}

This is the most important step. Making the class to implement an interface, we made it to be kind of generic. Now, the House class doesn’t have to have the responsibility to create the SecurityService instance nor to be tied to the specific security class type. This menas it could even use the a mock representation of the class instead. Let’s create it too. It all make sense in a moment, bear with me:

public with sharing class SecurityServiceMock
    implements SecurityService.ISecurityService {

    public Boolean IsCurrentUserAllowedToEnterValue {get; set;}

    public Boolean isCurrentUserAllowedToEnter() {
        return IsCurrentUserAllowedToEnterValue;
    }
}

As you can see, I have created an Apex property to let my unit test to set the service’s return value at run time.

This is all setup we need. As I said at the beginning, in a later post I’ll explain how this gets simplified thank to the StubProvider interface and how the powerful ApexMocks framework saves the day. But we have to walk before we run.

Replacement by Dependency Injection

Don’t let the name scare you. Dependency Injection is perhaps the simplest and most popular method to accomplish our goal. In a nutshell, the class that depends on another, gets the instance as a parameter (is injected) instead of constructing it by its own. I.e. House takes SecurityService as parameter. In this example I have changed the House class so that the SecurityService instance is given by the class constructor:

public with sharing class House {
    private Boolean isDoorOpen = false;
    private SecurityService.ISecurityService security;

    public House(ISecurityService security) {
        SecurityService.ISecurityService this.security = security;
    }

    public void openDoor() {
        Boolean userHasAccess = this.security.isCurrentUserAllowedToEnter();
        if (!userHasAccess) {
            throw new SecurityException('You do not have access to this house');
        }

        isDoorOpen = true;
    }
}

An alternative to this, is to add a setter method instead of a specific constructor. Something like public void setService(SecurityService.ISecuritySerivice service). That’d allow changing the security behaviour of an existing House instance or in other words you can also inject the security behaviour through that method. It is really up to you.

Now, let’s have a look at how the unit test get’s heavily simplified:

@isTest(isParallel=true)
private class HouseTests {
    @isTest
    private static void openDoor_userHasAccess_doorOpen() {
        // Given
        SecurityServiceMock securityMock = new SecurityServiceMock();
        securityMock.IsCurrentUserAllowedToEnterValue = true;

        // When
        House standardHouse = new House(securityMock);
        standardHouse.openDoor();

        // Then
        System.assert(standardHouse.isDoorOpen, 'The door should be open.');
    }
}

Note that, you can easily test the negative use case and catch the exception. This test is much quicker to run, it can be parallelised, and doesn’t need to know the internal data the SecurityService class needs to success.

The downside of this technique is that, if a class depends on more other classes, you’ll have to add more parameters to the constructor or create additional setter methods. It is worthwhile though!

Replacement by deferring construction

Actually, with dependency injection, we moved the SecurityService construction out from the House class. There are plenty of ways to do the same and we are about to see another one, but this time, the construction will be the SecurityService very own responsibility.

Let’s perform one little tweak more to the SecurityService class:

public with sharing class SecurityService implements ISecurityService {
    @TestVisible ISecurityService serviceInstance;

    public interface ISecurityService {
        Boolean isCurrentUserAllowedToEnter();
    }

    public static ISecurityService getInstance() {
        if (serviceInstance == null) {
            serviceInstance = new SecurityService();
        }
        return serviceInstance;
    }
}

And now, let’s go back to the House class and see how it should be used:

public with sharing class House {
    private Boolean isDoorOpen = false;

    public void openDoor() {
        SecurityService.ISecurityService security =
            SecurityService.getInstance();
        Boolean userHasAccess = security.isCurrentUserAllowedToEnter();

        if (!userHasAccess) {
            throw new SecurityException('You do not have access to this house');
        }

        isDoorOpen = true;
    }
}

I’m sure you already imagine how the unit test will get the advantage of this, but let’s see it in action anyway:

@isTest(isParallel=true)
private class HouseTests {
    @isTest
    private static void openDoor_userHasAccess_doorOpen() {
        // Given
        SecurityServiceMock securityMock = new SecurityServiceMock();
        securityMock.IsCurrentUserAllowedToEnterValue = true;
        SecurityService.serviceInstance = securityMock;

        // When
        House standardHouse = new House();
        standardHouse.openDoor();

        // Then
        System.assert(standardHouse.isDoorOpen,
            'The door should be open.');
    }
}

This is just a handy way I found to move construction of classes out and at the same time remove the need of cluttering the constructor or the number of apex properties. But don’t let these examples to limit your imagination. You can find your own method that fits best to your use case.

Probably you’ll find a lot of ideas if you review the behavioural design patterns. At the end of the day, do mocks is just a matter of replacing classes behaviour.

Wrap up and next steps

Now that you have seen the examples, scroll up and check if you can tick all the items listed at the beginning of the article. And all that with just a few simple changes! Let’s summarise them:

  • Make “services” to implement an interface (make them generic).
  • Create mock objects.
  • Delegate construction of objects to other classes.

Like any new skill in life, what you should do next is to practice. Practice a lot. At the beginning you’ll probably find it complex but it will make you get how is your app structured and how you should architect it from now on. You’ll end up creating your own method to do mocks, not necessarily the same ones I have shown you here. At some point it’ll become a second nature.

After some time practicing, I really recommend you to have a look to the Andrew Fawcett’s definition of Separation of Concerns in the first place. It is explained with Salesforce particularities in mind, so it is worth a read.

There are tons of good examples, tutorials, books, etc out there. But now you know what is necessary to differentiate what it is good for you and what it is not. You might for instance have a look to these two Trailhead modules:

When you feel comfortable with that, it will be the moment of applying the promised ApexMocks and I hope to see you in a later post to do it together.

Last but not least, don’t forget the integration tests. I think this recent Twitter thread really hits the spot:

testsAreForProgrammets

This will be always a largely discussed topic, but what it is clear in my opinion, is that unit tests aim to cover the scope of a specific method without its dependencies. That is where the mocking technique excels.

The post ends by saying:

[…] they are written by programmers for programmers.

Your unit tests protect every piece of your software safe from failures or unintended changes. Your integration and system tests however, will ensure the behaviour of your app works as expected/defined. You’ll still need integration tests, but it will be your responsibility to set the amount and the use cases covered (not code coverage).

My very own experience

I have to say that, my transition from “classic” integration tests to mocked unit tests was kind of easy. ApexMocks was originally created by Paul Hardaker and quickly adopted and extended by the FinancialForce fellows at the time I was working there. I got influenced by the enthusiasm of the brilliant people building it and others with previous experience on the Mockito framework. I still find programmers putting a lot of interest on mocks which is quite nice.

On the other hand, during my years of experience, I have encountered many developers out there who were a little reluctant to do tests with mocks based on a poor experience or bias, and many others to not have heard about them at all. To be honest, it was hard to me to get it at the beginning too! Sometimes I also found it difficult to convey the goods of this great tool. But it is something we get with the experience, so try to not give up!

I hope you found this article useful and you are ready to get started. Happy mocking!

One thought on “Mocking fundamentals – simple mocks without frameworks”

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s