Showing posts with label Apex testing. Show all posts
Showing posts with label Apex testing. Show all posts

Sunday, January 18, 2015

Curious Case of Disappearing ID

Problem

Last week, I was deploying some changes to the recently deployed Apex classes into the production, but somehow it was failing on previously migrated test classes that were not related to the changes being deployed. To confirm that it had something to do with production environment, rather than the new code, I ran those pre-existing test classes in the production environment, and they were indeed failing even without the changes (I also had them run in Sandbox and confirm that they passed).  My initial suspicion was that someone had added something like a validation rule on the sObjects for which I was generating test data.  Although it was related to the test records being generated, the problem, it turned out, was not related to the validation rule, but something rather more strange.

The test classes had a structure similar to the following where I had a static method to generate test data for all the test methods and a test method that queries for the test data.
@isTest private class TestCustomController {   static void createBackground() {     List<Account> testAccts = new List<Account> {       new Account(Name = 'Test Account 1'),       new Account(Name = 'Test Account 2')};     Database.insert(testAccts);
    List<Account_Child__c> children = new List<Account_Child__c> {       new Account_Child__c(Name = 'Child 1', Account__c = testAccts[0].id)};    Database.insert(children);   }
  static testMethod void manipulateCustomController() {     TestCustomController.createBackground();
    Account queriedAcct = [SELECT Id FROM Account WHERE Name = 'Test Account 1'];
    // Initialize custom controller, pass on the account ID,     //and call method to query for the children of the accounts.   } }
To debug the problem in the production, I had put breakpoints in the createBackground() method after the insertion of the account and in the manipulateCustomController() method after query for the account through Developer Console and ran this test class.  What I found out was that the ID of the Test Account 1 in the createBackground() didn't match the ID in the manipulateCustomController()!

Workaround

I tried moving the code in the createBackground() method into the manipulateCustomController() method, and that did resulted in the ID being consistent through out the run of that test method.  However, this did not completely solve the test failure as I had another weird issue where the symbol table not showing some properties of an in-memory instance of a sObject, while it showed in the heap.

Takeaway

This does demonstrate that there are major differences in the internal implementation of the Test and "Production" environments of the Salesforce, mainly that the Test environment is somewhat unstable and has weird kink in it.  Also, it does demonstrate how valuable breakpoints can be when debugging problem in the Production org. 

Monday, August 4, 2014

Validation, Approval Process and Testing

Two of the common sources of headache for Salesforce developer is approval process and validation.  Because these are declarative aspect of Salesforce (i.e. configured through the Salesforce user interface) with some restriction, these can be difficult to manager and migrate

With it being now migratable, many of the pain points for developing approval process in the sandbox has been removed.  However, once you activate an approval process, Salesforce removes some of the functionalities.  You can find more about these limitations here, but I found the following to be particularly difficult to deal with when you have changes in business logic and need to modify the approval process:

  • You cannot delete active approval process, and you can't deactivate an approval process if there is any records that are submitted for approval (you have to hard delete those records).
  • Once you activate an approval process, you can't add, delete or change the orders of the approval step even if you deactivate them.



With the validation rule, the difficulty I sometimes encounter is when trying to migrate some code and there is additional validation rule in the destination org (e.g. production or QA sandbox).  These validation rule can cause your test methods to fail in the destination org even though it has passed in the development org.  You can either create those validation rule in your development org and refactor your test methods to meet the validation rule, or if you are confident that the additional validation rule will not cause the business logic error when the new code is deployed, you can temporarily disable to the validation rule in the destination org during the migration and re-activate it afterwards.