To start using the ApexMocks framework, you first need to take a Dependency Injection approach to writing your software. Dependency Injection is one way of achieving a loosely coupled, highly cohesive design for your code.
Personally I prefer constructor injection (as opposed to setter injection – Constructor Versus Setter Injection).
At it’s simplest level all this means is that you pass a given class its dependencies via its constructor. In order to facilitate robust production code and the ability to inject mocks I settled on this pattern:
public class MyClass { private DependencyA.IDependencyA m_dependencyA; private DependencyB.IDependencyB m_dependencyB; public MyClass() { this(new DependencyA(), new DependencyB()); } @testVisible private MyClass(DependencyA.IDependencyA dependencyA, DependencyB.IDependencyB dependencyB) { this.dependencyA =dependencyA; this.dependencyB =dependencyB; }
The ‘real’ production code creates MyClass via the normal default constructor, which still executes the private testVisible constructor, passing in real instances of the dependencies.
The crucial thing is, this frees us up and allows our test to construct MyClass via the private constructor passing in mock versions of the dependencies.
@isTest private class MyClass { @isTest static void my_first_apex_mocks_test() { // Given ApexMocks mocks = new ApexMocks(); DependencyA.IDependencyA mockDependencyA = new MockDependencyA(mocks); DependencyB.IDependencyB mockDependencyB = new MockDependencyB(mocks); // When MyClass myClass = new MyClass(mockDependencyA, mockDependencyB); }
We can then verify that MyClass interacts correctly with its dependencies by writing behaviour verification unit tests.
And we can also stub out the dependencies using when() style dependency stubbing.
This approach even allows us to write DML free tests that never even touch the database, and consequently execute very quickly!
Next time we’ll see how to use the apex-mocks-generator tool to create mock implementations of our component interface.
neat use of the @testVisible scoped constructor.
Pingback: Verify call’s order in Apex unit tests – XoNoX Force
Pingback: Answering with Apex Mocks – XoNoX Force