Reader small image

You're reading from  Force.com Enterprise Architecture - Second Edition

Product typeBook
Published inMar 2017
Reading LevelIntermediate
PublisherPackt
ISBN-139781786463685
Edition2nd Edition
Languages
Right arrow
Author (1)
Andrew Fawcett
Andrew Fawcett
author image
Andrew Fawcett

Andrew Fawcett has over 30 years of experience holding several software development-related roles with a focus around enterprise-level product architecture. He is experienced in managing all aspects of the software development life cycle across various technology platforms, frameworks, industry design patterns, and methodologies. He is currently a VP, Product Management, and a Salesforce Certified Platform Developer II at Salesforce. He is responsible for several key platform features and emergent products for Salesforce. He is an avid blogger, open source contributor and project owner, and an experienced speaker. He loves watching movies, Formula 1 motor racing, and building Lego!
Read more about Andrew Fawcett

Right arrow

Chapter 12. Unit Testing

Unit testing is a key technique used by developers to maintain a healthy and robust code base. The approach allows developers to write smaller tests that invoke more varied permutations of a given method or a unit of code. Treating each method as a distinct testable piece of code means that not only current usage of that method is safer from regression, future usage is protected as well. It frees the developer to focus on more permutations, such as error scenarios and parameter values beyond those currently in use.

Unit testing is different from integration testing where many method invocations are tested as a part of an overall business process. Both have a place on Force.com. In this chapter we will explore when to use one over the other.

To understand how to adopt unit testing we first need to understand dependency injection. This is the ability to dynamically substitute the behavior of a dependent class' s methods with test or stub behavior. Using a so-called...

Comparing Unit testing and Integration Testing


Much of the difference between unit and integration testing relates to the scope of the code being tested and the goals of the test. Chances are you have been mixing a combination of the two on Force.com without realizing it.

First, let's consider this definition of Integration testing by Wikipedia:

Integration testing (sometimes called integration and testing, abbreviated I&T) is the phase in software testing in which individual software modules are combined and tested as a group. It occurs after unit testing and before validation testing. Integration testing takes as its input modules that have been unit tested, groups them in larger aggregates, applies tests defined in an integration test plan to those aggregates, and delivers as its output the integrated system ready for system testing.

In general, most published guidance on writing Apex tests falls into this integration testing category. Indeed, the only way to cover Apex Trigger code...

Dependency Injection, Mocking, and Unit Testing


At this stage, you're probably wondering just how is it technically possible, using code, to substitute or inject (to use the correct term) different compiled code during a test execution. To illustrate the various options for Dependency Injection let's start with a simple code example. We will explore how unit testing can be applied to Apex Enterprise patterns later in this chapter.

The following diagram shows the Unified Modeling Language (UML) for a Car class model, which has been designed with SOC in mind. Responsibilities such as engine, dashboard, and the digital readout display have been separated. This is a pure Apex code example to illustrate how dependencies between classes can be managed with Dependency Injection (DI):

The following code is for the Car class. It has a dependency on methods from the Dashboard and Engine classes. The caller must set up and provide instances of these classes for the methods to function correctly:

public...

Writing Unit Tests with the Apex Stub API


The Apex Stub API applies only within an Apex test context. So it cannot be used to implement DI outside of tests. For this you still need to leverage Apex interfaces.

Utilizing the APIs requires an understanding of the following:

  • Implementing the Stub Provider interface: The System.StubProvider system-provided Apex interface is effectively a callback style interface. It allows your mocking code to be informed when method calls are against classes you are mocking in your test. You can implement this interface multiple times, once per class you're mocking, or a single implementation for building sophisticated generalized mocking frameworks. The Apex Mocks open source framework from FinancialForce.com is one such framework that we will be reviewing later.

  • Dynamic Creation of Stubs for Mocking: The platform automatically creates instances of classes you wish to mock through the Test.createStub method. You do not need to create Apex interfaces to perform...

ApexMocks and Apex Enterprise Patterns


As we saw earlier, the supporting library or Apex Enterprise patterns provides methods that provide a Dependency Injection facility through the factories in the Application class. This facility is also compatible with the use of ApexMocks and Apex Stub API. The following sections contain examples of the use of ApexMocks to unit test the layers within the application architecture introduced in earlier chapters.

Unit Testing a Controller Method

The following test can be found in the RaceControllerTest class and demonstrates how to mock a service layer class:

@IsTest
private static void whenAwardPointsCalledIdPassedToService() {
    
    fflib_ApexMocks mocks = new fflib_ApexMocks();

  // Given
  RaceServiceImpl mockService = (RaceServiceImpl) mocks.factory(RaceServiceImpl.class);
  Application.Service.setMock(RaceService.class, mockService);
    
  // When
  Id raceId = fflib_IDGenerator.generate(Race__c.SObjectType);
  RaceController raceController = ...

Summary


Integration testing focuses on the scope of controller methods or APIs exposed via your services to test the full stack of your code. It requires setting up the database, executing the code to be tested and querying the database. These tests are critical to ensuring all the components of your application deliver the expected behavior.

In order to make the individual code components, classes and methods as robust and future proof as possible, developers can test each method in isolation without incurring the overhead of setting up the database or updating it. As such, unit tests run more quickly. Unit tests can increase coverage, as more corner cases testing scenarios can be emulated using mocking of scenarios that would otherwise be impossible or difficult to setup on the database.

Unit Testing requires an understanding of some other patterns such as Dependency Injection and mocking. Dependency Injection can be implemented in a number of ways, using constructors, factories and setter...

lock icon
The rest of the chapter is locked
You have been reading a chapter from
Force.com Enterprise Architecture - Second Edition
Published in: Mar 2017Publisher: PacktISBN-13: 9781786463685
Register for a free Packt account to unlock a world of extra content!
A free Packt account unlocks extra newsletters, articles, discounted offers, and much more. Start advancing your knowledge today.
undefined
Unlock this book and the full library FREE for 7 days
Get unlimited access to 7000+ expert-authored eBooks and videos courses covering every tech area you can think of
Renews at £13.99/month. Cancel anytime

Author (1)

author image
Andrew Fawcett

Andrew Fawcett has over 30 years of experience holding several software development-related roles with a focus around enterprise-level product architecture. He is experienced in managing all aspects of the software development life cycle across various technology platforms, frameworks, industry design patterns, and methodologies. He is currently a VP, Product Management, and a Salesforce Certified Platform Developer II at Salesforce. He is responsible for several key platform features and emergent products for Salesforce. He is an avid blogger, open source contributor and project owner, and an experienced speaker. He loves watching movies, Formula 1 motor racing, and building Lego!
Read more about Andrew Fawcett