The following post is based on an email I sent a student worker who, bless his heart, is doing terribly complicated and important, but also terribly boring, grunt work. As a thank-you, I'm giving him Apex coding projects to do in a Developer Org and granting him a block of time per day to work on them.
This morning, I'm working on writing a new "public" Apex method that, as a parameter, takes a set of Contact IDs. If a Contact's "Account.Name" is meaningless (e.g. "No Company Assigned,"), this method then checks to see if there is a non-null string in that Contact's "Company Holding Spot" custom field. If any such strings happen to match the Name of a record in our Accounts table, my new method populates the Contact's AccountId with the appropriate value. Hopefully, I can use this to clean up a bunch of old data in one fell swoop.
I'm writing the new method in test-driven-development style, which means I have my test fully ready to go before I've put any "action" code into my new method. Here's what that looks like:
@isTest public class ScratchPadClassTest { // Class-level static variables private static Boolean setupAlreadyRan = FALSE; private static UtilityDefaultInfoOftenNeeded useful; // The test method static testMethod void testCompanyHoldingSpotToAcctId() { runSetup(); // Set up a couple of test accounts (also remember that a 3rd "No Company Assigned" one exists thanks to "runSetup()") Account aMcD = new Account(Name='McDonalds'); Account aTgt = new Account(Name='Target'); insert new List<Account>{aMcD, aTgt}; // Set up a couple of test contacts who newly claim they work at McDonald's (but one of whom already worked somewhere else) Contact c1 = new Contact(LastName='McTestNullAcctNowMcD', AccountId=useful.getDefaultAccountId(), Company_Holding_Spot__c = 'mcdonalds'); Contact c2 = new Contact(LastName='McTestTgtAcctNowMcD', AccountId=aTgt.Id, Company_Holding_Spot__c = 'Mc. Donalds'); insert new List<Contact>{c1, c2}; Test.startTest(); // Call our data-transformation method on the IDs of our two contacts ScratchPadClass.copyCHSToAcct(new Set<Id>{c1.Id, c2.Id}); Test.stopTest(); // Pull a fresh copy of our contacts out of the database Map<Id, Contact> csAfter = new Map<Id, Contact>([SELECT Id, AccountId, Account.Name FROM Contact WHERE Id IN (:c1.Id, :c2.Id)]); // PERFORM TESTS CHECKING FOR DATA QUALITY // Since Contact #1 had a generic "No Company Assigned" account to start with, McD's should have propagated into AccountId System.assertEquals(aMcD.Id,csAfter.get(c1.Id).AccountId, 'c1 Account Name is ' + csAfter.get(c1.Id).Account.Name); // Contact #2 was already working at a real company (Target), don't overwrite w/ McD's. Needs human review. System.assertEquals(aTgt.Id,csAfter.get(c2.Id).AccountId, 'c2 Account Name is ' + csAfter.get(c2.Id).Account.Name); } // A private helper method private static void runSetup() { if (setupAlreadyRan == FALSE) { DefaultTestDataFactory.setUpCustomSettings(); if (useful==null) { useful = UtilityDefaultInfoOftenNeeded.getInstance(); } setupAlreadyRan = TRUE; } return; } }
NOTE: You might notice that I have classes called "DefaultTestDataFactory" and "UtilityDefaultInfoOftenNeeded" whose code isn't shown here. Don't worry about them. All they do that matters is to this code is:
- Insert a "No Company Assigned" account into the database (DefaultTestDataFactory) and
- Provide an easy way to retrieve the ID of that account (UtilityDefaultInfoOftenNeeded.getInstance().getDefaultAccountId())
The body of ScratchPadClass looks like this:
public class ScratchPadClass { public static void copyCHSToAcct(Set<Id> cIds) { return; } }
When I "Run Test" on "ScratchPadClassTest," the first System.AssertEquals fails with the following error message:
- Assertion Failed: c1 Account Name is No Company Assigned: Expected: 00738000006UTiPEDC, Actual: 00738000006UTiOEDC
In other words, I expected c1’s Account.Name to change from "No Company Assigned" to "McDonalds," but it didn’t happen.
Well, of course it didn’t happen. ScratchPadClass.copyCHSToAcct() doesn’t even do anything yet!
Now I will go write ScratchPadClass.copyCHSToAcct(). And I’ll know I wrote it correctly when my test passes.
And THAT’s test-driven development!
No comments:
Post a Comment