How to set a Lookup Field via a Salesforce Trigger - triggers

I want to set a Lookup Field using a salesforce apex trigger, but I keep getting an error:
System.StringException: Invalid id:
I have a custom object called Job__c. It has a custom pick list for accounts: Acct__c.
A user will populate Acct__c as John Deer, the trigger should add John Deer to the Account__c lookup field.
Here is the trigger:
trigger UpdateAccounts on Job__c (before insert) {
for (Job__c obj: trigger.new){
obj.Account__c = obj.Acct__c; //Exception is thrown here
}
Exception thrown:
System.StringException: Invalid id:
I tried something different:
List <Job__c> opListInsert = new List<Job__c>();
List <Job__c> opListUpdate = new List<Job__c>();
if(trigger.isInsert){
for(Job__c op:trigger.New){
if(op.Acct__c != Null){
op.Account__c = op.Acct__c;
opListInsert.add(op);
}
}
}
else if(trigger.isUpdate){
for(Job__c op:trigger.New){
if(op.Acct__c != Null && op.Acct__c !=trigger.oldMap.get(op.id).Acct__c){
op.Account__c = op.Acct__c;
opListUpdate.add(op);
}
}
}
That code throws:
Error:Apex trigger UpdateAccounts caused an unexpected exception, contact your
administrator: UpdateAccounts: execution of BeforeUpdate caused by:
System.StringException: Invalid id:
What am I doing wrong that it tells me it's an invalid ID?

Account__c is a look-up field, you cannot assign a string (the picklist field) to it. Instead you have to assign it an account id.
I am not sure why you're using the account names in the picklist field, but if you want to continue doing that then there's a simple solution that the account names are unique.
Get the id for the account selected in the query for the id, something like this:
list<account> acclist = [select id from account where name In yourNameList];
And then in the trigger reference the id
obj.account__c = accList[0].id;
Make use of maps , do not add the soql's inside for loop

You have to set your field with the ID of the object you want it to link to.
The salesforce browser page has a handy dandy tool that lets you put in incomplete information into the lookup field, and it fills it in for you automatically. This does not happen when values are assigned manually with an apex statement. You can only set the value to a valid and existing ID of the object the lookup was set to link to.
This code will grab the ID given name and do what you wanted:
trigger UpdateAcct on Job__c (before insert, before update) {
List<String> Accounts = new List<String>();
for (Job__c obj: trigger.new){
Accounts.add(obj.Acct__c);
}
list<Account> acctlist = [select Name from account where Name in :Accounts];
if (acctlist.size() > 0 ){
for (Integer i = 0; i < Trigger.new.size(); i++)
{
if (Trigger.new[i].Acct__c != null)
{
Trigger.new[i].Account__c = acctlist[i].ID;
}
else
{
Trigger.new[i].Account__c = null;
}
}
}
}

Related

Salesforce Apex Trigger data copy from one field to other

This is my Apex Trigger in which I am taking data from Custom Field "Picklist Multiple" named(Opportunity_Picklist__c) in Opportunity and automatically paste it to a custom field "text" in Account. Now every selected option from Custom Field "Picklist Multiple" is coming to the custom field "text". I want to copy only Custom Field "Picklist Multiple" values with API Name "Premium" and "Basic". Other selected values can be avoided. Please look into the code below and suggest me relatable changes.
Custom Field "Picklist Multiple" have these data:-
Premium
Advanced
Basic
Free
If someone selected all four values in Custom Field "Picklist Multiple" they can remain as it is but I don't want all of them to be copied in custom field "text". I want the values with API Names "Premium" and "Basic" only in the custom field "text".
trigger OppTrigger on Opportunity (After insert,After update,After delete) {
if((Trigger.isInsert|| Trigger.isupdate|| Trigger.isDelete) && Trigger.isAfter)
{
Set<Id> acctSet = new Set<Id>();
List<Account> accList = new List<Account>();
for(Opportunity opp : Trigger.new)
{
acctSet.add(opp.AccountId);
}
Map<Id, Account> mapAccounts = new Map<Id, Account>([SELECT Id, Plan__c FROM Account where Id IN :acctSet]);
for(Opportunity opp : Trigger.new)
{
Account acc = mapAccounts.get(opp.AccountId);
If(Trigger.IsDelete){
acc.Plan__c = null;
}
if(Trigger.isInsert|| Trigger.isupdate){
acc.Plan__c = opp.Opportunity_Picklist__c;
}
accList.add(acc);
}
Update accList;
}
}
You'll be better off cutting it up a bit. Use a helper class as trigger handler. Will let you create some reusable functions rather than just a giant block of code executing top-down. There's this for general reading, I like that one but there are lots of examples, what you'll be comfortable with.
For example imagine a method called static void rollupToAccounts(Set<Id> ids). It'd accept account ids and you could call it from different scenarios (because you'll have different entry points. Insert is easy, base it on trigger.new, cool. Delete is funnier because there's no trigger.new, you need to get Account Ids out of trigger.old And after update if I move opportunity from Account A to B - your code should recalculate both! Good luck writing straight in the trigger's body.
As for actual "meat" of the method... many ways to do it, something like this?
static void rollupToAccounts(Set<Id> ids){
final Set<String> valuesToRollup = new Set<String>{'Premium', 'Basic'};
List<Account> toUpdate = new List<Account>();
List<Account> accounts = [SELECT Id, Plan__c,
(SELECT Opportunity_Picklist__c
FROM Opportunities
WHERE Opportunity_Picklist__c INCLUDES :valuesToRollup)
FROM Account WHERE Id IN :ids];
for(Account a : accounts){
Set<String> currentValues new Set<String>();
if(String.isNotBlank(a.Plan__c)){
currentValues.addAll(a.Plan__c.split(';'));
}
Set<String> newValues = new Set<String>();
if(!a.Opportunities.isEmpty()){
for(Opportunity o : a.Opportunities){
newValues.addAll(o.Opportunity_Picklist__c.split(';')); // this will include Advanced & Free too, it's ok, we'll fix it
}
newValues.retainAll(valuesToRollup); // filter out all the ones we don't want
}
System.debug('old: ' + currentValues + '; new: ' + newValues);
if(currentValues != newValues){
// we'll need to update this account with current data
List<String> temp = new List<String>(currentValues);
temp.sort();
a.Plan__c = String.join(temp, ';');
toUpdate.add(a);
}
}
System.debug(toUpdate);
update toUpdate;
}
It's not perfect. If you have 100 opportunities for same account with "Basic" it'll take them all and possibly waste query rows. You could do it as 2 (sub)queries, WHERE Opportunity_Picklist__c INCLUDES ('Basic') LIMIT 1 and then another query for Premium if you think it'd be a problem..
Why not just check the value of the opportunity picklist before saving it into the account value? You could write this code a little cleaner and more efficient. However, a simple solution is just to check if the values you want exist.
if(Trigger.isInsert|| Trigger.isupdate){
String strAccountPlan;
if(opp.Opportunity__PickList__c.Contains('Premium'){
strAccountPlan = 'Premium';
}
if(opp.Opportunity__PickList__c.Containt('Basic'){
if(String.isBlank(strAccountPlan){
strAccountPlan = 'Basic');
}
else{
strAccountPlan += ';Basic';
}
acc.Plan__c = strAccountPlan;
}

Apex Salesforce Updating Field from Other Entity only getting 1 value on Bulk insert

Tried to make that title as specific as possible. Sorry if it is long.
Basically, what is happening is that I have a trigger that looks up a match (on email) to a custom object. If the email matches. I need to pull information from the custom object (Member Verification) and put that in a field (custom field) on the Lead object.
This is working fine for individuals. But when I do a bulk import, every Lead ends up with the same value, instead of the unique value that it should be matching by email address. I have tried about 6 different methods, and all of them look like they should work. But I have no idea what I am missing. Any help would be greatly appreciated.
The code is below:
trigger UpdateVerifyLead on Lead (before insert, before update) {
List<String> leadEmails = new List<String>();
Map<String, Member_Verification__c > MVEmailMap = new Map<String, Member_Verification__c >(
[SELECT Id, Primary_Email__c,TFA_Salesforce_ID__C FROM Member_Verification__c WHERE Primary_Email__c != null and Primary_Email__c IN :leadEmails]);
for(Lead lead:Trigger.new){
leadEmails.add(lead.Email);
for(Lead leadObj:Trigger.new){
if(MVEmailmap.containsKey(leadObj.Email)){
lead.TFA_Salesforce_ID__c = MVEmailmap.get(leadObj.Email).TFA_Salesforce_ID__C ;
lead.Verified__c = True;
MVEmailmap.clear();
}
}
}
You're instantiating the map using a query, which is fine if you need to have Ids as keys, but I'm not sure it works with your email field as a key.
You'll need an extra iteration to populate the map.
Something like this should work:
trigger UpdateVerifyLead on Lead (before insert, before update) {
List<String> leadEmails = new List<String>();
Map<String, Member_Verification__c> MVEmailMap = new Map<String, Member_Verification__c>();
// first iteration to get the emails
for(Lead lead:Trigger.new){
leadEmails.add(lead.Email);
}
// populate the map, dropping the != null, shouldn't be necessary
for(Member_Verification__c memberVerification:[SELECT Id, Primary_Email__c,TFA_Salesforce_ID__C FROM Member_Verification__c WHERE Primary_Email__c IN :leadEmails]){
MVEmailMap.put(memberVerification.Primary_Email__c,memberVerification);
}
// final iteration to set the member verification
for(Lead leadObj:Trigger.new){
if(MVEmailmap.containsKey(leadObj.Email)){
lead.TFA_Salesforce_ID__c = MVEmailmap.get(leadObj.Email).TFA_Salesforce_ID__C;
lead.Verified__c = True;
}
}
}

Trigger to copy image from child record to parent record

I am trying to write a trigger that will update a RTA field on a parent object with an image from a RTA field on the child object.
I am getting the below error when creating the child object
Apex trigger Updateparent caused an unexpected exception, contact your administrator: Updateparent: execution of AfterInsert caused by: System.StringException: Invalid id: (.....IMAGE IS DISPLAYED HERE....)External entry point.
Info
Man Utd is the child object
Account is the parent object
Image__c is the RTA field on the child object
Copy_image__c is the RTA field on accounts
Here is the trigger code
trigger Updateparent on Man_Utd_1__c (after insert, after update) {
Map<ID, Account> parentAccounts = new Map<ID, Account>();
List<Id> listIds = new List<Id>();
for (Man_Utd_1__c childObj : Trigger.new) {
listIds.add(childObj.Image__c);
}
parentAccounts = new Map<Id, Account>([SELECT id, (SELECT ID, Image__c FROM Man_Utd_s__r) FROM Account WHERE ID IN :listIds]);
for (Man_Utd_1__c manu : Trigger.new) {
Account myParentAccounts = parentAccounts.get(manu.Image__c);
myParentAccounts.Copy_image__c = manu.Image__c;
}
update parentAccounts.values();
}
Can anyone advise on how to rectify this or if it is even possible to do?
EDIT to answer comments
This one works for me, there's a slight modification around the null check. Give it a go? The field is called Image__c both on Account and Contact.
trigger rollupImage on Contact (after insert, after update) {
Set<Account> parents = new Set<Account>();
for (Contact child : trigger.new) {
if(child.AccountId != null && child.Image__c != null){
parents.add(new Account(Id = child.AccountId, Image__c = child.Image__c));
}
}
if(!parents.isEmpty()){
List<Account> toUpdate = new List<Account>();
toUpdate.addAll(parents);
update toUpdate;
}
}
ORIGINAL
The error
It's all written there ;)
List<Id> listIds = new List<Id>();
for (Man_Utd_1__c childObj : Trigger.new) {
listIds.add(childObj.Image__c); // boom happens here?
}
You're assigning rich text area value (very long string with encoded image in it) to Id variable (15 or 18 char special string)
Try like this:
Set<Id> ids = new Set<Id>(); // Set will ensure we won't have duplicate values
for (Man_Utd_1__c childObj : Trigger.new) {
ids.add(childObj.Account__c);
}
Optimization - round 1
In the second loop you're setting the Copy_Image__c field but on the local copy of Account (local variable in the scope of the loop). I'm not sure setting it there will propagate the change to the parent acc (it might be a full copy and not a reference to the item in the map. You could put it back (parentAccounts.put(manu.Account__c, myParentAccounts)) to the map or just do the image assignment directly:
parentAccounts = new Map<Id, Account>([SELECT id FROM Account WHERE ID IN :ids]);
// I've removed the subquery, you don't need it, right?
for (Man_Utd_1__c manu : Trigger.new) {
if(parentAccounts.containsKey(manu.Account__c)){
parentAccounts.get(manu.Account__c).Copy_image__c = manu.Image__c;
}
}
update parentAccounts.values();
Optimization - round 2
It looks bit stupid - we query for Accounts but all we need to fetch is the Id... But we know the Id already, right? So - behold this "pro trick" (shared just because my colleague is a big fan of Man U ;))
trigger Updateparent on Man_Utd_1__c (after insert, after update) {
Set<Account> parents = new Set<Account>();
for (Man_Utd_1__c child : trigger.new) {
if(child.Account__c != null){
parents.add(new Account(Id = child.Account__c, Copy_Image__c = child.Image__c));
}
}
if(!parents.isEmpty()){
List<Account> toUpdate = new List<Account>();
toUpdate.addAll(parents);
update toUpdate;
}
}
Note: Optimization is the key thing while writing trigger.
While writing trigger make sure you follow all the best practises:
Keynotes On Trigger:
OPTIMIZATION - I have specified it in Uppercase and in first line because its the key thing while writing logic
Proper indentation and code commenting, so that anyone who works on the same code will easily understand the logic by just glancing on the comments. Make sure you update lastModifiedBy line on initial comments so that it will be helpful to keep a trace who worked last/updated last and on what date. Better keep proper code comments on every line- IF NEEDED ONLY
Variables with proper names ex: if var of list type then 'lst' prefix or 'List' postfix and then the proper name ex: lstContactsToInsert OR lstContactsToUpdate
Always create a seperate handler class and don't write all the logics on trigger itself 'AS A BEST PRACTISE TO FOLLOW'
Have proper trigger contexts. Know when to use proper trigger contexts through salesforce documentations on trigger. Use 'Before' contexts if it can be handled using this, If Not then go for 'After' contexts so you limit DML's.
Keynotes On Handler:
The First 3 steps as mentioned for trigger applies here as well
Use common private methods where you write logic and use it in other methods
Keynotes On TestClass:
Always write a test class utilizing 'GENERIC TEST DATA CLASS' in your test class.
Use proper test method names like: test_Method_One 'OR' testImageUpdates as such
Use asserts and test all usecases - Both negative and positive tests
#1. Trigger
/**
* #TriggerName : ContactTrigger
* #CreatedBy : Rajesh Kamath
* #CreatedOn : 30-Nov, 2016
* #Description : Trigger to update the image on parent object 'Account' based on the child object 'Contact'
* #LastModified: None
*/
trigger ContactTrigger on Contact(after insert, after update) {
//Instantiate the handler class
ContactTriggerHandler objContactHandler = new ContactTriggerHandler();
/* Trigger Context */
if(Trigger.isAfter) {
//Fire on Insert
if(Trigger.isInsert) {
objContactHandler.onAfterInsert(trigger.new);
}
//Fire on Update
if(Trigger.isUpdate) {
objContactHandler.onAfterUpdate(trigger.new, trigger.oldMap);
}
}
}
#2. Handler
/**
* #HandlerName : ContactTriggerHandler
* #TriggerName : ContactTrigger
* #TestClassName : ContactTriggerHandlerTest [Make sure you create this with the steps at the end of this handler]
* #CreatedBy : Rajesh Kamath
* #CreatedOn : 30-Nov, 2016
* #Description : Trigger to update the image on parent object 'Account' based on the child object 'Contact'
* #LastModified: None
*/
public with sharing class ContactTriggerHandler {
/*
#MethodName : onAfterInsert
#Parameters : List<Contact> lstNewContactRecords
#LastModifiedBy : None [Make sure when anyone updates even this line will be updated for help for other users who work on later phase]
*/
public void onAfterInsert(List<Contact> lstNewContactRecords){
//Call a common method where we have logic
reflectChildImageOnParent(lstNewContactRecords, null);
}
/*
#MethodName : onAfterUpdate
#Parameters : List<Contact> lstContactRecords, Map<Id, Contact> mapOldContactRecords
#LastModifiedBy : None [Make sure when anyone updates even this line will be updated for help for other users who work on later phase]
*/
public void onAfterUpdate(List<Contact> lstContactRecords, Map<Id, Contact> mapOldContactRecords){
//Call a common method where we have logic
reflectChildImageOnParent(lstContactRecords, mapOldContactRecords);
}
/*
#MethodName : reflectChildImageOnParent
#Parameters : List<Contact> lstContactRecords, Map<Id, Contact> mapOldContactRecords
#LastModifiedBy : None [Make sure when anyone updates even this line will be updated for help for other users who work on later phase]
*/
private static void reflectChildImageOnParent(List<Contact> lstContactRecords, Map<Id, Contact> mapOldContactRecords){
/* Local variable declaration */
List<Account> lstAccountsToUpdate = new List<Account>();
for(Contact objContact : lstContactRecords) {
//Execute on insert and update
if((Trigger.isInsert || (Trigger.isUpdate && objContact.Child_Image__c != mapOldContactRecords.get(objContact.Id).Child_Image__c)) && objContact.Account__c != null) {
//List of accounts to update
lstAccountsToUpdate.add(new Account(Id = objContact.Account__c, Parent_Image__c = objContact.Child_Image__c));
}
}
//Update the account records
if(!lstAccountsToUpdate.isEmpty()) {
update lstAccountsToUpdate;
}
}
}
This can be referred for your usecase.
Please mark as 'Best Answer' if this was helpful
loyalty - Child Obj
fields:
lightingdata__Contact__c (relationship)
lightingdata__imagenims__c // Image field
Contact - Parent Obj
field: lightingdata__Imagefromloyalty__c
trigger loyaltytocon on Loyalty__c (after insert, after update) {
Map<id, Contact> conlist;
List<Id> idlist=new List<id>();
for (Loyalty__c loy:trigger.new) {
idlist.add(loy.lightingdata__Contact__c);
}
conlist= new Map<id, contact>([select id, lightingdata__Imagefromloyalty__c from contact where id In : idlist]);
for(Loyalty__c lo:trigger.new){
contact con = conlist.get(lo.lightingdata__Contact__c) ;
system.debug('con data' + con);
con.lightingdata__Imagefromloyalty__c = lo.lightingdata__imagenims__c;
}
update conlist.values();
}
In pareant object field it will return that image filed have URL.
Then you can create one formula filed and just refer (lightingdata__Imagefromloyalty__c) in formul it will display the image.

Apex - Salesforce.com - I need help writing an APEX class to test my working trigger - Chatter - Monitor specific keywords

Here is my working trigger
trigger CheckChatterPostsOnNSP on FeedItem (before insert) {
Set<Id> nspIds = new Set<Id>();
//Get the NSP that will be updated
List<Non_Standard_Pricing__c> nsp2Update = new List<Non_Standard_Pricing__c>();
//Get the key prefix for the NSP object via a describe call.
String nspKeyPrefix = Non_Standard_Pricing__c.sObjectType.getDescribe().getKeyPrefix();
//Get the Id of the user
Id profileId = UserInfo.getProfileId();
for (FeedItem f: trigger.new) {
String parentId = f.parentId;
if(profileId == '00e30000000eWXR') {// Users profile must be Sales and Service
//We compare the start of the 'parentID' field to the NSP key prefix to
//restrict the trigger to act on posts made to the NSP object.
if (
parentId.startsWith(nspKeyPrefix) &&
(
f.Body.contains('***APPROVED BY CHANNEL***') ||
f.Body.contains('***APPROVED BY CSM***') ||
f.Body.contains('[APPROVED BY CHANNEL]') ||
f.Body.contains('[APPROVED BY CSM]')
)
){
nspIds.add(f.parentId);
}
}
}
List < Non_Standard_Pricing__c > nsps = [select id, Pre_Approved_Service_Discount__c, ownerId
from Non_Standard_Pricing__c where id in :nspIds];
for (Non_Standard_Pricing__c n: nsps) {
//We compare the creator of the Chatter post to the NSP Owner to ensure
//that only authorized users can close the NSP using the special Chatter 'hot-key'
n.Pre_Approved_Service_Discount__c = true;
nsp2Update.add(n);
}
update nsp2Update;
}
Here is my attempt to write an APEX Test Class
#isTest
public class CheckChatterPostsOnNSPTEST {
static testMethod void CheckChatterPostsOnNSPTEST() {
//Create and insert opp
Opportunity opp = new Opportunity(Name='test opp', StageName='stage', Probability = 95, CloseDate=system.today());
insert opp;
//Create and insert NSP
Non_Standard_Pricing__c NSP = new Non_Standard_Pricing__c(Opportunity__c = opp.Id, Status__c = 'Open');
insert NSP;
//Find user with Profile = Sales and Service
Profile SalesNService = [Select id from Profile where Name = 'Sales and Service' limit 1];
User u = new User(
Alias = 'standt',
Email='standarduser#testorg.com',
EmailEncodingKey='UTF-8',
LastName='Testing',
LanguageLocaleKey='en_US',
LocaleSidKey='en_US',
ProfileId = SalesNService.Id,
TimeZoneSidKey='America/Los_Angeles',
UserName='standarduser#testorg.com'
);
System.runAs(u)
{
//Create FeedItem entry with text '[APPROVED BY CHANNEL]'
FeedItem post = new FeedItem();
post.body = '[APPROVED BY CHANNEL]';
//Now update the opportunites to invoke the trigger
Test.startTest();
insert post;
Test.stopTest();
}
//Assertion Testing
for(Opportunity o : [select Id, Name, Primary_NSP__r.Pre_Approved_Service_Discount__c from Opportunity where Id = :opp.Id]){
system.assert(o.Primary_NSP__r.Pre_Approved_Service_Discount__c = true);
}
}
}
I'm getting the following errors
Message: System.QueryException: List has no rows for assignment to SObject
Stack Trace: Class.CheckChatterPostsOnNSPTEST.CheckChatterPostsOnNSPTEST: line 14, column 1
Any help is greatly appreciated.
That'd be pointing to this line:
Profile SalesNService = [Select id from Profile where Name = 'Sales and Service' limit 1];
Simply check if this query returns something? Typo in the profile name (maybe you have them with underscores or "Sales & Service")? Maybe there's no such profile in org at all (for example if you've created such one on production but the sandbox you're in was not refreshed afterwards)?
I'm afraid we can't help you more than that ;) It can't be even related to API versions, "seeAllData" etc because docs say Profiles are still visible.

Apex Trigger Works, can not get test pass

I came back to this 3 hours later and with no changes to any code, test execution worked.
Disregard This Question
I have written a trigger that works great for setting the accountID on a contact record based on an external ID.
I had a test that worked great, but I added some logic to the trigger so it only updates contacts with a 'Default Account' as account. Now my test fails saying it did not update the account even though it still works as designed when saving records.
What am I missing?
I added line 4
ID DefaultAccID = [select ID from Account where Name = 'Default Account'].ID;
and the if around line 9
if (contactNew.AccountID == DefaultAccID) {
}
to Trigger:
trigger TRG_Contact_SetHouseholdID on Contact (before update, before insert) {
Set<String> AccIDlist = new Set<String>();
ID DefaultAccID = [select ID from Account where Name = 'Default Account'].ID;
// loop through records finding thoes that need to be linked
for(Contact contactNew:Trigger.New){
if (contactNew.AccountID == DefaultAccID) {
AccIDlist.add(contactNew.RPHouseholdID__c);
}
}
Map<String, ID> AccountMap = new Map<String, ID>();
//loop needing linked and get account ID if it exist
for(Account oneAccount:[SELECT RPHouseholdID__c, ID from Account where RPHouseholdID__c IN :AccIDlist]){
AccountMap.put(oneAccount.RPHouseholdID__c, oneAccount.ID);
}
// loop through records updating the ones that need link
for(Contact contactNew:Trigger.New){
if (AccountMap.get(contactNew.RPHouseholdID__c) <> null){
contactNew.AccountID = AccountMap.get(contactNew.RPHouseholdID__c);
}
}
}
Test Class:
#isTest
Private class TRG_Contact_SetHouseholdID_Test {
static TestMethod void Test0_TestInsertWithValue(){
insertTestAccounts();
Account defaultAccount = [select ID from Account where name = 'Default Account' limit 1];
Account newAccount = [select ID from Account where name = 'Camper Family' limit 1];
test.startTest();
insertTestContact(defaultAccount.ID);
test.stopTest();
Contact newContact = [select ID,AccountID from Contact where firstname = 'Happy' and lastname = 'Camper' limit 1];
System.assertEquals(newContact.AccountID, newAccount.ID, 'accountID did not get changed from default (' + defaultAccount.ID + ')');
}
private static void insertTestAccounts()
{
Account obj = new Account();
obj.Name = 'Default Account';
insert obj;
obj = new Account() ;
obj.Name = 'Camper Family';
obj.RPHouseholdID__c = '111';
insert obj;
}
private static void insertTestContact(ID defaultID)
{
Contact obj = new Contact();
obj.AccountID = defaultID;
obj.firstName = 'Happy';
obj.lastname = 'Camper';
obj.RPHouseholdID__c = '111';
insert obj;
}
}
Expanding a bit on #zachelrath 's answer, beginning with API version 24.0, test methods are isolated from the data in the organization (with a few exceptions User, RecordType, etc. see here for the full list). Rather than changing the API version of the file, the easiest thing to do is to add the see all data directive to the isTest annotation, like so:
#isTest(SeeAllData=true)
Private class TRG_Contact_SetHouseholdID_Test {
// etc
Set your test class' API version to 24.0 --- I'd bet your initial query for the Default Account is pulling in a preexisting record whose Name is 'Default Account', instead of the Default Account you're creating in your test data. There are 2 ways to get around this:
(Easiest) Change your test class to API version 24.0
If you would rather stay in API 23.0 or lower, then, at the start of your test method, delete all accounts named 'Default Account', then insert your test accounts.