3

Why do we sometimes add a new record to an object and then just return the variable and sometimes we insert it too. I am confused, can somebody clarify me on this?

1 Answer 1

5

There's actually three different designs: insert and return, return without insert, and optional insert and return. All of the methods are more or less the same, it's mostly a matter of preference.

The automatic insert design saves on code, as all the DML operations are self-contained. This also reduces flexibility, for example, you can't necessarily use these methods when testing callouts, or it may artificially increase DML operations. Also, sometimes you need a non-inserted object, such as testing a Visualforce controller that works on a new record.

The return without insert method increases the size of unit tests, but also increases flexibility, since developers are now in control of when they would like to use DML statements; they can also combine multiple DML calls in to a single operation. This is also better for situations where you only work on records in memory and no DML is necessary.

The optional insert design offers the best of the other two options. Developers can opt for automatic inserts when they need them, and still have the flexibility to combine DML operations or just create records that don't need to be inserted (such as testing some Visualforce controllers, etc).

The most important consideration should be consistency. All methods should use the same design, so developers don't need to read the source code for each method to see if they need to manually insert the records. Consistent unit test frameworks are more important than choosing a specific model, although I would strongly recommend not automatically inserting the records in any case, since it's often more convenient to have an option to insert or not.

6
  • awesome. thanks! Optional insert sounds like passing a Boolean into a method? Apr 19, 2021 at 15:54
  • 1
    @Dextersecret That's the most typical model. It would make more sense to ask "do I typically want to insert data" and go with the model that works best. We don't use this method because our tests create everything in testSetup using a utility method that creates a ton of data used in our tests. It's even more efficient at the cost of sometimes creating records we don't need.
    – sfdcfox
    Apr 19, 2021 at 16:26
  • Sounds like your test setup also strives for most comprehensive realism. Also having a single class to manage and call must be saving bunch of time. I will try this option for our test framework. thanks Apr 19, 2021 at 19:44
  • 1
    @Dextersecret I don't know the exact metrics, but our utility class probably cuts off 30+ minutes per RunAllTests. It models the data, but also utilizes our "kill switch" code to prevent any triggers from running. This saves something like ~5 seconds per class with some odd 400 unit test classes.
    – sfdcfox
    Apr 19, 2021 at 19:56
  • 1
    @Dextersecret We have a TriggerFramework class with the functions pushState, popState, enableAll, disableAll, enableTrigger(String), disableTrigger(String), and isTriggerEnabled(String) that we can use to selectively enable and disable triggers. Each trigger starts off with If(!TriggerFramework.isTriggerEnabled('TriggerName')) { return; } This is not persisted to the database, as it is meant exclusively for testing. I had a more powerful one that used CustomSettings in another project, but was deemed overkill for our purposes.
    – sfdcfox
    Apr 19, 2021 at 20:59

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.