I would like to check if my understanding is correct and also would like some help in how to handle a particular scenario with test case executions.

I have been writing test cases for all the Apex classes, triggers, etc. I have custom data objects and of course CRUD operations on these classes. I know about the annotation @seeAllData=true. Some people suggested removing this to test the insert/update/delete operations as this affects the data in the Org.

However, I would like to run these operations with the above annotation so that I can also test all the exception handling and other cases(update if the record is already present, etc.). If I don't use the annotation, all these erroneous scenarios are avoided. I have added them too and it works quite well. But how can I make a full set of CRUD operations transactional? For e.g. I am worried what if my test cases are running and there is an error after an insert and a delete operation fails in my test cases. This loads the org with unwanted data. Can it be handled in some way?

Thanks for any help.


Changes to data you make in test context are not persisted past the end of the test method, whether or not you use the seeAllData=true annotation. The purpose of that annotation is to allow tests to see the data in your org, but it does not allow test data to persist, regardless of whether an exception is thrown.

However, you should virtually never use seeAllData=true in new unit tests, and it should be removed from existing unit tests whenever possible. That's because that annotation breaks the isolation between test and production context in a different way: it makes the tests dependent on the data in your org, which makes the tests fragile - their behavior can change based on data changes, even if your code still works correctly. Unit tests that have that type of data dependency are unreliable and of limited value.

It is important, as you note, to test edge cases - weird data, exception handling, and other things that don't represent the normal execution path of the code. However, you should always create those situations within test context, by creating and, if necessary, inserting records that represent those exceptions. For example, if your code works on the children of some parent record that should always have children, you should test it against a new parent record created in the test case that doesn't have children, so you can validate its behavior.

There are some edge cases that you don't need to or cannot test, it's true. You shouldn't bother testing that the platform behaves as documented, as a general rule. If you insert an object, you don't need to assert() that its Id is not null: that would only prove that the Salesforce platform isn't breaking one of its core commitments.

There's also situations where it's difficult to generate data that represents, for example, legacy production data created before a new validation rule was introduced and which breaks invariants expected by the code. Dependency injection can often help with those situations, but they're pretty case-specific.

  • Wow, thank you for the detailed answer. It pretty much answers everything I need.
    – Randomizer
    Aug 24 '18 at 13:21

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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