Showing posts with label unit test. Show all posts
Showing posts with label unit test. Show all posts

Friday, February 21, 2014

"Illegally" Reparenting Children in Master-Detail Relationship with Apex

If you have a Master-Detail field in Salesforce that's not reparentable, what do you think will happen if you use Apex to change the field value on a record? I had expected to see an exception thrown. But after a few hours of head-scratching, I discovered I was wrong.

If you try to change the value of a Master-Detail field that is not configured so that "child records can be reparented," you will not see an error. Salesforce will simply leave the existing value in place as if you never attempted to make the change in the first place.

The interesting implication here is that developers should write Apex tests to validate expected an Master-Detail configuration. Admins and developers can work together more reliably, if you explicitly write an Apex test that confirms whether a Master-Detail field can be reparented. This way, when an admin changes the field configuration and unintentionally breaks something, a red flag will be raised by the test method, pointing you clearly to the unexpected configuration change.

To see what happens if you reparent a child record when that's not "allowed", try this:
  1. Create a custom object labeled "Alias" (Alias__c), with the record name configured as a text field
  2. Create a Master-Detail field on Alias labeled "Account" (Account__c)
  3. Configure the Account field on Alias so that child records cannot be reparented to other parent records after they are created
  4. Create an AliasUtilTest class, as seen in this paste, with a test method to assert that changing the Account field on an alias is a futile effort
  5. Run the test method in AliasUtilTest

Friday, December 20, 2013

Testing Apex @future Methods in Salesforce

To write functional Apex unit tests for methods having the future annotation, all you need to do is use Test.startTest() and Test.stopTest(). The general structure of your testMethod will look like the following.

Whether it's scheduled Apex or @future Apex, calling Test.stopTest() will cause those methods to run in sequence in your test method. Test.stopTest() then allows you to validate the results of @future Apex using normal means.

Friday, October 4, 2013

Force.com #Tested, Standard Pattern for Apex Unit Tests

The first step to writing an Apex unit test is... just to lay down the framework. The boring stuff, really. Declare the class, add the isTest annotation, declare a testMethod-qualified method, etc. And to make boring matters worse, in practice Apex unit testing is pretty important to get right.

The reason is simple: In addition to deploying your own customizations, Salesforce will upgrade your org 3 times a year with 100+ new features per release. Whether you like it or not. Assuming CRM is fairly important to your organization, who's going to run tests for your org every time a new release happens, to make sure the business can continue to operate?

  • Code coverage and test methods are intended to make sure that customizations work correctly, release after release, with minimal human effort
  • Good tests help to make sure your code works not only for one-off record edits but also for batch inserts, updates and deletes
  • With good intent, Salesforce requires you to have at least 75% code coverage to deploy new code. So, if you have to write tests anyway, let's just do it right the first time. Build the tests to add value as regression tests, instead of just time drains.


Understanding the significance of these tests, a new developer may find writing good tests to be quite daunting, second-guessing himself and worrying about whether he followed best practices. Then, in frustration, he could decide to just "screw it" and hack something out to achieve the minimum amount of code coverage required to just push a risky feature into production. Bad outcome.

To help a developer avoid this sub-optimal decision, he can adopt a standard test class structure that is easily adapted for all Apex unit tests. Below is one such self-documenting template for Apex unit tests, using a contrived example of trying to roll-up all activities related to a particular contact record.


There are lots of comments and little code in the above block, which is intentional to leave material for the rest of this series. :-) Subsequent posts will dive into each step above in more detail, walking through sample implementations by building out this example trigger test class.

But regardless of whether you're testing triggers, controllers, extensions, Schedulables or anything else in Apex, the general steps above should remain the same for your test methods. This way, Apex unit tests transform from time-and-materials liabilities in a Salesforce org to valuable assets that shine every time anyone goes to release a new feature.

Wednesday, September 25, 2013

Force.com #Tested, Way Beyond Code Coverage

Force.com gives developers a quick and easy way to not only deploy business automation but also to set up unit tests for acceptance testing and regression testing. The value of such testing cannot be underestimated, especially in large orgs with multiple admins, developers and outsourced partners.

While the ideals are good, there are many challenges preventing an organization from reaching these goals. Managers may not fully understand the benefits of unit testing, and as a result have little or no buy-in for the practice. Without buy-in from managers, there is no enforcement of consistent methodologies for internal and external developers. Frustrated developers who don't have management support, training or knowledge on unit tests only see the code coverage portion of unit testing and feel that the practice is a big pain with little gain.

But actually, proper and disciplined use of unit tests on Force.com allows a company to:
  • More reliably implement new features by explicitly testing for expected functionality using Apex
  • Simplify regression testing by allowing the system to automatically perform acceptance tests that were used when deploying previous features to production
  • More confidently allow developers to simultaneously tackle multiple work streams for different features, knowing that both each other's functionality and previous functionality will be validated together before new features goes live
  • Define functional specifications for external parties through unit tests, in addition to written requirements

This blog mini-series aims to address the challenges above by sequentially tackling the following topics, with new posts every 3 business days:
  1. Standard pattern for Apex unit tests
  2. Common database of test data for all Apex unit tests
  3. Using System.assert() and related methods to verify expected conditions for the test
  4. Using Test.startTest(), Test.stopTest() and other Test methods
  5. Using System.assert() and related methods for validating test results
  6. Apex unit tests for workflow rules, validation rules and system configurations
  7. How this standard pattern affects code coverage