Since it is unit test code, you should know how many Contacts will be added to the same parent account
Thus, your ApexMocks verify for
unitOfWork.registerNew(new Contact(
LastName = 'Test contact'
), Contact.AccountId, acc);
will be
Integer expectedContactsPerAccount = 3;
((fflib_SObjectUnitOfWork) mocks.verify(mockUow,mocks
.times(expectedContactsPerAccount)
.description('should be ' + expectedContactsPerAccount + ' contacts added to Account 'testAccount')))
.registerNew(fflib_Match.sObjectWith(new Map<SObjectField,Object> {
Contact.LastName => 'Test contact'
}),
fflib_Match.eqSObjectField(Contact.AccountId),
fflib_Match.sObjectWith(new Map<SObjectField,Object> {
Account.Name => 'Test acc'
}));
Now, if your code under test could create two Accounts with the same Account.Name
and there is no other distinguishing field between the two Accounts, I'd suggest redesigning your application as creating multiple Accounts with the same Name doesn't seem like good design.
I don't see how ArgumentCaptors will help as acc.Id
is local to the code under test and you won't have that unless the method returns the inserted Accounts so you can then in turn verify the second registerNew
Another approach would be to move the account creation into a different service class and use Apex Mocks answers to return a mocked Account (including Account.Id). Then, you could verify the second registerNew of Contacts against the Apex Mocks Answers of the simulated inserted Accounts. See Answering with ApexMocks
But frankly, when faced with your situation, I'd design my unit test to avoid creating Accounts with duplicate names (and no other disambiguation) so I could reliably verify the registerNew for Contact.