(Been spending quite a bit of time learning ApexMocks in conjunction with fflib pattern). Example simplified from more involved code
Class/method under test
public class Foo {
public void doWork() {
fflib_ISobjectUnitOfWork uow = Application.UnitOfWork.newInstance();
uow.registerNew(new list<Account> {
new Account(Name='A0', Website = 'www.salesforce.com'),
new Account(Name='A1', Website = 'www.google.com')
};
uow.registerNew(new list<Bar__c> {
new Bar__c(Name = 'Bar0', FieldX__c = 'x0')
}
uow.commitWork();
}
}
testMethod
private class TestApexMocks {
@isTest private static void testUoW() {
fflib_ApexMocks mocks = new fflib_ApexMocks();
// Given mock implementation of UnitOfWork
fflib_SobjectUnitOfWork mockUow = (fflib_SobjectUnitOfWork) mocks.mock(fflib_SObjectUnitOfWork.class);
Application.UnitOfWork.setMock(mockUow);
// When method invoked
new Foo().doWork();
// Then verify new SObjects were created ...
The only thing I could get to work was this convoluted approach using ArgumentCaptors...
fflib_ArgumentCaptor insertedSobjectsArgument= fflib_ArgumentCaptor.forClass(list<SObject>.class);
((fflib_SObjectUnitOfWork) mocks.verify(mockUow,2))
.registerNew((SObject[])insertedSobjectsArgument.capture());
// extract the captured Sobjects arguments to the mocked UoW from a list<ANY>
Object[] actualInsertedSObjects = insertedSobjectsArgument.getAllValues();
Account[] actualAccounts;
Bar__c[] actualBars;
for (Object o: actualInsertedSObjects) {
if (o instanceOf list<Account>)
actualAccounts = new list<Account>((Account[])o);
else
if (o instanceOf list<Bar__c>)
actualBars = new list<Bar__c>((Bar__c[])o);
}
// do asserts against actualAccounts and actualBars
I tried using the fflib_Match.sObjectWith
matcher in a .verify but this matcher only applies to a single Sobject and registerNew
is invoked with lists so there was no match.
The ArgumentCaptor method getAllValues()
returns a list of Object
where each Object
is itself a list of SObject
. I couldn't think of a cleaner way to cast this to the SObjects I cared about (Account
, Bar__c
)
There ought to be a way to do this with matchers and the .verify(..)
method but I couldn't figure it out.
Editorial remark: The syntax for ApexMocks is not obvious for the beginner and there is a lot of casting required. Matchers are vital but the documentation examples don't tend to use collections and collections of SObjects so this can get frustrating
Answers/comments of the form - just query for the sobjects and assert are not on point. The point of the question is how to do this with ApexMocks, not how to test DML statements