mitchspano/apex-trigger-actions-framework

FinalizerHandlerTest.finalizerThatInvokesDmlShouldCauseException

bloerinczCBS-CX opened this issue · 5 comments

Expected Behavior

Test classes should run without problems in existing orgs. The test classes of the Apex Trigger Actions Framework should run in existing orgs regardless of customizing, e.g. validation rules.

Actual Behavior

The test method finalizerThatInvokesDmlShouldCauseException of the test class FinalizerHandlerTest fails if a validation rule exists for the account.

Steps to Reproduce the Problem

  1. Deploy framework into an scratch org.
  2. Create validation rule on object Account, for example: ISBLANK(BillingStreet)
  3. Run FinalizerHandlerTest.finalizerThatInvokesDmlShouldCauseException
  4. Monitor test result: System.AssertException: Assertion Failed: The exception should have the correct message: Expected: DML is not allowed within the finalizer context., Actual: Insert failed. First exception on row 0; first error: FIELD_CUSTOM_VALIDATION_EXCEPTION, Billing Street required: [BillingStreet]

Specifications

  • Version:
  • Platform:

"Test classes should run without problems in existing orgs"

I'm not sure this is true...

This is certainly not the case for packages on the app exchange. As a package developer, we can't really be responsible for what the subscriber has in their org - particularly when DML operations are performed.

I suppose we could mock the Limits class to insulate as much as possible, but there is only so much we can do.

Also, package tests are executed at package version generation time - not version installation time, so the tests should always be protected from whatever is in the subscribers org.

@mitchspano in general, I agree that tests with DML statements in packages won't work in most subscriber orgs. But in this case, it looks like the test is doing insert new Account(Name = 'Acme'); - you could change it to do a (pointless) update on user instead, and it would work in all orgs. Something like update new User(Id = UserInfo.getUserId());

@mitchspano: Yes, regarding managed packages (on the AppExchange) you are absolutely right. I thought this should be true as well for frameworks, which can be deployed without installing a package, as I did in the past with the fflib packages or the trigger framework of Kevin O'hara, etc. I thought it would be great if no one has to adjust the coding to get the framework working in their org and for updates to be able to simply over-deploy without manual adjustments on every update of the framework.

@jongpie: Thanks for the idea, that should work out.

@jongpie: I thought I would quickly provide a PR in my lunch break. I was surprised that it didn't work out:

Update failed. First exception on row 0 with id 0051l0000095WUqAAM; first error: APEX_DATA_ACCESS_RESTRICTION, In parallel Apex tests, DML operations aren't permitted on this type of object: User: []

https://ideas.salesforce.com/s/idea/a0B8W00000GdZgcUAF/allow-dml-on-user-object-for-parallel-testing-apexdataaccessrestriction

My next idea of update new Organization(Id = UserInfo.getOrganizationId()); doesn't work as well, since "DML operation Update not allowed on Organization".

Any other ideas?

This issue is also affecting our org since the tests are included in LocalTests for deployments. I've updated the test locally, but would love a solution that doesn't require reimplementing when updates are installed.

@benjaminloerincz
Would using Database.setSavepoint(); work here, as it would increase the DML limit used? Or does it have to be an sobject?