No comments yet

Mocking Apex Tests

Enterprise Apex Design Patterns have been around for a while to represent best practices for large scale development projects. In this post we will talk about Mocking Apex Tests and Apex Mocks examples. We can significantly increase the project quality by combining different test techniques and also reduce the overall test execution time the project build pipeline will be grateful.

Using patterns like AAA helps us to have more organized and easy-to-read tests. Using a framework like the Mocker Framework to hide the low-level mocks creation complexity moves the developer focus to what matters, the test implementation.

What are Mock classes and Why do I need it?

It’s for any project team that wants to increase the software quality and decrease the test development time.

  • Improve project testability.
  • Decrease test running time.
  • Create more reliable tests.
  • Design a loosely coupled project architecture.
  • Hide the unit tests complexity behind a framework.

Unit Tests Vs Integration Tests

Integration Tests :The integration tests are responsible for testing if different modules or services from the application work well together.

Unit Tests : The unit tests are low-level and close to the application source code. They consist of testing individual methods and functions of the classes, components or modules.

Before Implementing the Unit Tests

The AAA Structure

The test is divided into 3 sections:

Arrange: Initializes objects and data to be used on the test.

Act: Invokes the method under test with the arranged data.

Assert: Verifies if the method under test behaves as expected.

Mocking The Dependencies

  1. We need to create mock objects for the class dependencies.
  2. The class to be tested should allow us to replace its dependencies instances.

Salesforce STUB API

Allow us:

  • To create mocked objects
  • To handle method calls
  • To read the method arguments
  • To define the method return value

However:

  • It’s a low level API
  • It’s necessary to implement the Stub Provider interface
  • It’s no easy to understand and use

Mocking Framework

The Mocker Framework, It encapsulates the STUB API complexity exposing an easy-to-use fluent interface. It records the expected mock behavior and replicates this behavior during the test execution phase. It also collect the execution statistics that can be asserted on the assertion phase.

The Mocker Framework Phases

Mocker works in three phases: Stubbing, Executing (Replaying) and Asserting phases.

  • Stubbing phase: Mocker will record the mock actions and expected behaviours;
  • Executing phase: It will replay the recorded mock object actions and execution statistics;
  • Asserting phase: It will assert if the class under test has executed the expected behaviour;

The Mocker Framework Architecture

Start stubbing phase

Mocker mocker = Mocker.start.Stubbing()
ContactSelector selector = mocker.mock(ContactSelector.class)

Record the expected behaviour

mocker.when(selector.getContactsBĀName(‘Leo’))
.thenReturn(new List< > { new Contact(‘Leo’) });
mocker.when(selector.getContactsBĀName(‘Gsc’))
.thenThrow(new MĀEÿception('Test eÿception'));

Start the execution phase

mocker.stopStubbing();
// Eÿecute the tests

Start the assertion phase

mocker.assert();

Preparing Your Class for Unit Testing

Decoupling you code : To create a proper unit test the developer needs to have access to the class dependencies and replace them with mocked classes. How can I decouple the following dependency?

1. Passing Dependencies Through The Class Constructor

The Tested Class dependencies will be received through the class constructor. Usually we use this approach with some Dependency Injection framework.

2. Using an IOC Container

The class dependencies will be received through an IOC container. During the testing phase we can instruct the IOC container to return the mock instance instead of the real implementation.

3. Using @TestVisible on Private Properties

The class dependencies will be created using private properties. Those dependencies can be replaced for the mock instances during the unit testing.

Let’s talk about Unit Testing Code

Given the following dependency class…

public class MĀSelector {
public Contact getContactBĀEmail(String email) {
return [
SELECT Id, Name
FROM Contact WHERE Email = :email
LIMIT 1
];
}
}

And the following Service class to be tested…

Mocking the Method Return for specific parameter values

Mocking Exceptions

// Arrange
//.
mocker.when(mĀSelectorMock.getContactBĀEmail('leo@eÿample.com'))
.thenReturn(new Contact(FirstName = 'Leo'));
// Recording the eÿception behaviour
mocker.when(mĀSelectorMock.getContactBĀEmail('nicolas@eÿample.com'))
.thenThrow(new MĀEÿception('Test'));
// Going to the eÿecution phase
mocker.stopStubbing();
// Act first call
Contact contact1 = new MĀService().getContact('leo@eÿample.com'); // It will return Leo contact
trĀ {
// Act eÿception call
new MĀService().getContact('nicolas@eÿample.com'); // It will throw MĀEÿception
SĀstem.assert(false, ‘The eÿception MĀEÿception should be thrown’);
} catch(Eÿception e) {
// Assert
}

There are four method behaviors that we can assert:

  • shouldBeCalledOnce();
  • shouldBeCalled(Integer times);
  • shouldNeverBeCalled();
  • shouldBeCalledBetween(Integer minTimes, Integer maxTimes);

Agenda

  • Unit Tests x Integration Tests
  • How to create unit tests for your application
  • Preparing your classes for unit testing
  • Using Mocker Framework to mock your dependencies
  • Mocking exceptions
  • Adding expected methods behavior
  • Asserting captured arguments

Post a comment