Last time we saw how to verify the behaviour of our components using verify() based unit tests.
The other beauty of a mocking framework is that it allows you to stub dependencies so you can focus on unit testing the logic of the component you are working on, without worrying about having to use real versions of dependencies.
For example, suppose you are creating a component like a VisualForce controller extension, which uses a service class to interact with business logic (see Apex Enterprise Patterns).
Traditionally, to unit test your VF controller, you would need to create records and insert them in the database, so that your service class will then load the necessary data when it is used by the controller extension.
But with the ApexMocks framework, you can stub your service class to return whatever data you like – and it doesn’t have to even exist on the database.
This means less setup for your test and also the test will run much more quickly because it doesn’t have to interact with a real version of your service class, which in turn means no interaction with the database. So we can write DML free unit tests.
To give a simple example, say we want to stub a CarService to return some data such that we can test a CarControllerExtension:
@isTest private class CarControllerExtensionUnitTest { @isTest static void bookingCarServiceShouldTakeUserToServicingPage() { // Given ApexMocks mocks = new ApexMocks(); CarService.ICarService mockCarService = new MockCarService(mocks); // Create our custom object but don't insert it into the database Car__c car = ObjectBuilder.createCar().withName('Audi'). // Use the ApexMocks IDGenerator to create a dummy Salesforce Id for our object. // In reality we would probably get our ObjectBuilder to do this for us. Id carId = IDGenerator.generate(Car__c.SObjectType); car.Id = carId. // Use ApexMocks to stub the return value for the service's getCar() method mocks.startStubbing(); mocks.when(mockCarService.getCar(carId)).thenReturn(car); mocks.stopStubbing(); // When CarControllerExtension carControllerExtension = new CarControllerExtension(mockCarService); PageReference carServicePageRef = carControllerExtension.bookCarService(carId); // Then System.assertEquals('myExpectedPageRef', carServicePageRef.getUrl()); } }
Anyone familiar with mockito syntax should recognise the when() call immediately, apart from the startStubbing() and stopStubbing() calls.
In this test we have also used an ObjectBuilder with a fluent API for creating our test object, and the ApexMocks IDGenerator to create a fake Salesforce Id.
ApexMocks frees you up to stub any of your Apex classes which should transform the way you are able to write unit tests for the Force.com platform.
The key thing to focus on is testing the logic of your class/component, and to use mock versions of it’s depdendencies where appropriate. But don’t mock yourself into a corner – mocks are very powerful, but can be overused.
Where can I find ObjectBuilder.cls that you’ve used on your code? I’m curious to see that fluent class!
That’s a fairly easy thing to write, I’ll blog some example code soon!
I need that ObjectBuilder as well. When we can expect to have it?
Hi there,
ObjectBuilder is really just a pattern you can implement any time on your own
Hello, were you able to work around formula fields? I have some methods that depending on a value of a formula field do some thing or the other. I’m able to mock the query that returns all the values, as I stub it and return the record I created in the test, but i’m not able to populate the formula field to make it work properly. Is there a way to make it works?
Pingback: Counters in Apex Mocks verifications – XoNoX Force
Pingback: Verify call’s order in Apex unit tests – XoNoX Force
Pingback: Answering with Apex Mocks – XoNoX Force