apex-enterprise-patterns / fflib-apex-mocks

An Apex mocking framework for true unit testing in Salesforce, with Stub API support
BSD 3-Clause "New" or "Revised" License
423 stars 214 forks source link

sObjectWith Matcher issue when uow.registerNew, uow.registerDirty on same object #65

Closed cropredyHelix closed 6 years ago

cropredyHelix commented 6 years ago

I'm not sure there is an answer to this but consider the following (assumes fflib Unit Of Work pattern)

Account a = new Account (Name = 'Foo');
uow.registerNew(a);
a.Name = 'Bar';
uow.registerDirty(a);

and this verify ...

((fflib_SobjectUnitOfWork) mocks.verify(mockUow,mocks.times(1)
                                              .description('1 Account sb inserted')))
    .registerNew(fflib_Match.sObjectWith(new map<SObjectField,Object> {
                    Account.Name => 'Foo'
            }));

The verify actually fails because the in-memory version of the Account a used in the uow.registerNew has changed after the registerNew was performed. When the mocks.verify executes, a.Name = 'Bar' !

This was a bit counterintuitive to me as I was expecting the mocking system to capture the arguments at the time of the uow.registerNew(a) and thus be verifiable later.

Now, why did this issue come up? I had a bulk processor that was accepting events from a 3rd party system. Within the transaction, new Accounts would be created (uow.registerNew) but if the same account was found later in the batch, a uow.registerDirty would be done on the Sobject held in memory from the insert. I relied on the fact that fflib_SObjectUnitOfWork does inserts first, then updates, so the coding pattern worked well.

Obviously, I can rework the verify statement but if there's a technical solution to this, that would be great.

cropredyHelix commented 6 years ago

errant issue