function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
tcash21tcash21 

Writing my first trigger and test case

Hi all,

 

I'm writing my very first bit of code in Apex. I'd like to write a trigger that updates a Lead's Status to "Working" as soon as the Lead Owner is changed.

 

Here's my trigger:

trigger test on Lead (after update) {
  Lead leadOld = trigger.old[0];
  Lead leadNew = trigger.new[0];
	if(leadOld.OwnerId != leadNew.OwnerId){
		leadNew.Status = 'Working';
	}
}

 

Here's my attempt at simply modifying the Apex docs test code:

 

@isTest
private class LeadStatusOwnerTriggerTest{

static TestMethod void TestInsert()
{
    //First, prepare 200 Leads for the test data
    Account acct = new Account(name='test account');
    insert acct;
    
    Lead[] leadsToCreate = new Lead[]{};
    for(Integer x=0; x<200;x++){
        Lead ld = new Lead(OwnerId=acct.OwnerId,lastname='testing',firstname='apex');
        leadsToCreate.add(ld);
    }
    
    //Now insert data
    Test.startTest();
    insert leadsToCreate;
    Test.stopTest();    
    
    }
}

 

I am getting this error:

System.DmlException: Insert failed. First exception on row 0; first error: INVALID_CROSS_REFERENCE_KEY, Owner ID: owner cannot be blank: [OwnerId]    LeadStatusOwnerTriggerTest.cls  SFDC/src/classes    line 18    Force.com run test failure

Also, I know I will eventually need to change the Lead OwnerId to fully test my trigger, but that field is not writeable.

 

Thanks for any help.

tcash21tcash21

Ok I finally figured it out. Phew. That was fun.

 

But for some reason I had to change my trigger to 'before' update rather than 'after' update.
Hard to tell when to use before vs after? Anyone care to enlighten me?!

Starz26Starz26

before is used to modify the records prior to insertion / update. Yo can directly access and update fields without having to do DML. Other more complicated scenerios exist but that is the basic.

 

After triggers are useful for evaluating things that may have changed due to workflows, formulas, etc as a result of the insert / update. Also useful for updating other records after the before events have occured.

 

There are also special considerations:

 

trigger.old is only available in update / delete.

trigger.new is not available in delete

you cannot update the records without using DML in before triggers

and others...

 

 

 

Also, if you need an ID for the insertion of a record, you must use after insert.

 

try this Link: http://www.salesforce.com/us/developer/docs/apexcode/Content/apex_triggers.htm

 

A

tcash21tcash21

If you can believe it, I've changed the test code around and somehow am not covering my test case anymore... grr.

 

Please help!

 

Trigger:

trigger UpdateLeadStatus on Lead (before update) {
 Lead leadOld = trigger.old[0];
 Lead leadNew = trigger.new[0];
	if(leadOld.OwnerId != leadNew.OwnerId){
		leadNew.Status = 'Working';
	}
}

 

Test:

@isTest
private class LeadStatusOwnerTriggerTest{

	static TestMethod void Test_LeadOwnerChange()
	{
		//First prepare two accounts for test data
		Account a = new Account(Name = 'Test Account A');
		Account b = new Account(Name = 'Test Account B');
		insert a;
		insert b;
	
		Account SOAccountA = [Select OwnerId, Name from Account where Id = :a.Id];	
		Account SOAccountB = [Select OwnerId, Name from Account where Id = :b.Id];	
	
		Lead[] leadsToCreate = new Lead[]{};
		for(Integer x=0; x<200;x++){
			Lead ld = new Lead(OwnerId=SOAccountA.OwnerId, Company='apex', lastname='testing',firstname='apex');
			leadsToCreate.add(ld); 
		}
	
		//Now insert data
		Test.startTest();
		insert leadsToCreate;
		Test.stopTest();    
	
		Lead ld = new Lead(OwnerId=SOAccountA.OwnerId, Company='apex', lastname='testing',firstname='apex');
		Lead ld2 = new Lead(OwnerId=SOAccountB.OwnerId, Company='apex', lastname='blah',firstname='blah');
	
		insert ld;
		insert ld2;
		
		//Query for ld2's OwnerID
		Lead lda = [Select OwnerId, Name from Lead where Id = :ld2.Id];	
		
		//Change ld's OwnerID to ld's and update
		ld.OwnerId = lda.OwnerId;
		update ld;
	}

}

 

tcash21tcash21

Deleting my local files and restarting Force.com IDE did the trick :/

 

Am I doing the below the best way possible though? I don't see the need to insert 200 records since I'm only checking one lead vs one lead. How can I even update 100s of leads without doing the update call in a for loop?

 

Thanks everyone.

Starz26Starz26

You are correct, no need to insert 200 records. HOWEVER, that in and of itself is a problem as your trigger is not able to handle bulk record insert / updates