The Apex Mocks framework gained a new feature recently, namely Matchers. This new feature means that we can start verifying what records and their fields values are being passed to a mocked Unit Of Work more reliably and with a greater level of detail.
Since the Unit Of Work deals primarily with SObject types this does present some challenges to the default behaviour of Apex Mocks. Stephen Willcock‘s excellent blog points out the reasons behind this with some great examples. In addition prior to the matchers functionality, you could not verify your interest in a specific field value of a record, passed to registerDirty for example.
So first consider the following test code that does not use matchers.
@IsTest
private static void callingApplyDiscountShouldCalcDiscountAndRegisterDirty()
{
// Create mocks
fflib_ApexMocks mocks = new fflib_ApexMocks();
fflib_ISObjectUnitOfWork uowMock = new fflib_SObjectMocks.SObjectUnitOfWork(mocks);
// Given
Opportunity opp = new Opportunity(
Id = fflib_IDGenerator.generate(Opportunity.SObjectType),
Name = 'Test Opportunity',
StageName = 'Open',
Amount = 1000,
CloseDate = System.today());
Application.UnitOfWork.setMock(new List<Opportunity> { opp };);
// When
IOpportunities opps =
Opportunities.newInstance(testOppsList);
opps.applyDiscount(10, uowMock);
// Then
((fflib_ISObjectUnitOfWork)
mocks.verify(uowMock, 1)).registerDirty(
new Opportunity(
Id = opp.Id,
Name = 'Test Opportunity',
StageName = 'Open',
Amount = 900,
CloseDate = System.today()));
}
On the face of it, it looks like it should correctly verify that an updated Opportunity record with 10% removed from the Amount was passed to the Unit Of Work. But this fails with an assert claiming the method was not called. The main reason for this is its a new instance and this is not what the mock recorded. Changing it to verify with the test record instance works, but this only verifies the test record was passed, the Amount could be anything.
// Then ((fflib_ISObjectUnitOfWork) mocks.verify(uowMock, 1)).registerDirty(opp);
The solution is to use the new Matchers functionality for SObject’s. This time we can verify that a record was passed to the registerDirty method, that it was the one we expected by its Id and critically the correct Amount was set.
// Then
((fflib_ISObjectUnitOfWork)
mocks.verify(uowMock, 1)).registerDirty(
fflib_Match.sObjectWith(
new Map<SObjectField, Object>{
Opportunity.Id => opp.Id,
Opportunity.Amount => 900} ));
There is also methods fflib_Match.sObjectWithName and fflib_Match.sObjectWithId as kind of short hands if you just want to check these specific fields. The Matcher framework is hugely powerful, with many more useful matchers. So i encourage you to take a deeper look David Frudd‘s excellent blog post here to learn more.
If you want to know more about how Apex Mocks integrates with the Apex Enterprise Patterns as shown in the example above, refer to this two part series here.









‘m proud to host my first guest blogger! 


You might be thinking having started to read this blog that the primary use case of 



Either way i knew i had to have some kind of physical field other than a Formula field on the Quote Line Item object to notify the rollup tool of a change that would trigger a recalculate of the Quote > Total. I called this field Amount (Shadow) in this case, i also left it off my layout.








