+ Start a Discussion
Developer.mikie.Apex.StudentDeveloper.mikie.Apex.Student 

Help writing Test code for trigger

Hey guys, can I get a little help with writing some Test code. I have tried and tried but still cannot write a bit of code which will pass more than 41%. The trigger I am testing changes its name whenever A contact is added or deleted to include the names: Example: 
An account with Jane and Ben samol would be called: Samol, Jane and Samol, Ben

This is my test code:

@isTest
private class TestAccountNameTrigger {
    static testMethod void validateAccountNameTrigger() {
//create test data

      
       Account a = new Account(Name='test');
       insert a;
       Contact C = new Contact(FirstName='test1',lastName='test2', accountid = a.Id);
       insert c;

       // Retrieve data
       a = [Select ID, Name  From Account WHERE ID = a.Id];
       System.debug('Value after trigger fired: ' + a.name);

       // Test that the trigger correctly updated the name
       System.assertEquals('test2, test1',a.name);
    }
}


This is my trigger:

trigger AccountNameTrigger on Contact (after insert,after update, after delete, after undelete) {
    Set<ID> setAccountIDs = new Set<ID>();
   
       
     if(trigger.isdelete)
{
    for(Contact c : Trigger.old)
   {
        setAccountIds.add(c.Accountid);
    }
}else
{

   
    for(Contact c : Trigger.new){
        setAccountIDs.add(c.AccountId);
    }
 
    List<Account> accounts = [Select ID, Name,(Select FirstName, LastName From Contacts)  From Account WHERE ID IN :setAccountIDs];
    for(Account a : accounts){
        String accName = '';
        Boolean hit = false;
        for(Contact c : a.Contacts){
             if(hit)
             {
                    accName+=' and ';
              }
          
             accName += c.LastName+', '+c.FirstName; 
             hit = true;                 
        }
        a.Name=accName;
    }
   
    update accounts;
 
}

}

Best Answer chosen by Developer.mikie.Apex.Student
Rahul SharmaRahul Sharma
Try this-

//////////////////////////////////////////////////Code Start//////////////////////////////////////////////////
@isTest
private class TestAccountNameTrigger3 {
    static testMethod void validateAccountNameTrigger3() {
   
       Test.startTest();
      
       //create test data
       Account objAccount = new Account(Name='test',Client_Branch__c='Gold Coast');
       insert objAccount;
      
       // Cover insert case
       // Inserting a contact
       Contact objContact = new Contact(FirstName='firstName1',
        lastName='lastName1',
        accountid = objAccount.Id);
       insert objContact;
    
       // Retrieve data
       objAccount = [Select ID, Name  From Account WHERE Id = objAccount.Id];
       System.debug('Value after trigger fired: ' + objAccount.name);

       // Test that the trigger correctly updated the name
       System.assertEquals('lastName1, firstName1',objAccount.name);
    
       // Cover update case
       objContact = contact(FirstName='firstName2',lastName='lastName2',Id = objContact.Id);
       update objContact;
    
       // Assert Account's Name field on update
       System.assertEquals('lastName2, firstName2',objAccount.name);
     
       //Cover second insert
       Contact objContact2 = new Contact(FirstName='firstName3',
        lastName='lastName3',
        accountid = objAccount.Id);
       insert objContact2;
    
       // Retrieve data
       objAccount = [Select ID, Name  From Account WHERE ID = objAccount.Id];
       System.debug('Value after trigger fired: ' + objAccount.name);

       // Test that the trigger correctly updated the name for second contact
       System.assertEquals('lastName1, firstName1 and lastName3, firstName3',objAccount.name);
    
       // cover delete case
       delete objContact;
    
  
       // Retrieve data
       objAccount = [Select ID, Name  From Account WHERE ID = objAccount.Id];
       System.debug('Value after trigger fired: ' + objAccount.name);

       // Test that the trigger correctly updated the name on delete
       System.assertEquals('lastName3, firstName3',objAccount.name);
    
       // cover undelete case
       // Use all rows filter in soql to retrieve deleted record
       objContact = [SELECT Id FROM Contact WHERE Id =: objContact.Id ALL ROWS];
       undelete objContact;
    
       // Assert Account's Name field on undelete
        objAccount = [Select ID, Name  From Account WHERE ID = objAccount.Id];
       System.debug('Value after trigger fired: ' + objAccount.name);
     
       System.assertEquals('lastName1, firstName1 and lastName3, firstName3',objAccount.name);
    
       Test.stopTest();
    }
}

//////////////////////////////////////////////////Code end//////////////////////////////////////////////////

All Answers

Rahul SharmaRahul Sharma
Hi Mikie,

Tried to write pseudo code for test class.

//////////////////////////////////////////////////Code Start//////////////////////////////////////////////////
@isTest
private class TestAccountNameTrigger {
    static testMethod void validateAccountNameTrigger() {
     
      //create test data
       Account objAccount = new Account(Name='test');
       insert objAccount;
      
       Test.startTest();
      
       // Cover insert case
       // Inserting a contact
       Contact objContact = new Contact(FirstName='firstName1',
        lastName='lastName1',
        accountid = objAccount.Id);
       insert objContact;
      
       // Retrieve data
       objAccount = [Select ID, Name  From Account WHERE ID = objAccount.Id];
       System.debug('Value after trigger fired: ' + objAccount.name);

       // Test that the trigger correctly updated the name
       System.assertEquals('lastName1, firstName1',objAccount.name);
      
       // Cover update case
       objContact = new Contact(FirstName='firstName2',
        lastName='lastName2',
        Id = objContact.Id);
       insert objContact;
      
       // Assert Account's Name field on update
       // to do
      
       // cover delete case
       delete objContact;
      
       // Assert Account's Name field on delete
       // to do
      
       // cover undelete case
       // Use all rows filter in soql to retrieve deleted record
       objContact = [SELECT Id FROM Contact WHERE Id =: objContact.Id ALL ROWS];
       undelete objContact;
      
       // Assert Account's Name field on undelete
       // to do
      
       Test.stopTest();
    }
}
//////////////////////////////////////////////////Code End//////////////////////////////////////////////////

Let me know what didn't work. Hope it helps in understanding.

Thanks,
Rahul
Developer.mikie.Apex.StudentDeveloper.mikie.Apex.Student
Hey rahul,

I think I understood what you are doing there. You are saying that you have to test for all scenarios and not just one. The code looks perfect..but for some reason it errors on line 19 because of objAccount.id. I have no idea why though? 

Isnt this adding the account objAccount?

Account objAccount = new Account(Name='test');
       insert objAccount;

Thank you so much for your help
Developer.mikie.Apex.StudentDeveloper.mikie.Apex.Student
This was my attempt at adding the missing bits...tell me what you think. It is still saying: "unexpected token: 'objAccount.Id' at line 19 column 62


@isTest
private class TestAccountNameTrigger3 {
    static testMethod void validateAccountNameTrigger3() {
    
      //create test data
       Account objAccount = new Account(Name='test',Client_Branch__c='Gold Coast');
       insert objAccount;
     
Test.startTest();
     
       // Cover insert case
       // Inserting a contact
       Contact objContact = new Contact(FirstName='firstName1',
        lastName='lastName1',
        accountid = objAccount.Id);
       insert objContact;
     
       // Retrieve data
       objAccount = [Select ID, Name  From Account WHERE ID = objAccount.Id];
       System.debug('Value after trigger fired: ' + objAccount.name);

       // Test that the trigger correctly updated the name
       System.assertEquals('lastName1, firstName1',objAccount.name);
     
       // Cover update case
       objContact = contact(FirstName='firstName2',lastName='lastName2',Id = objContact.Id);
       update objContact;
     
       // Assert Account's Name field on update
       System.assertEquals('lastName2, firstName2',objAccount.name);
      
       //Cover second insert
       Contact objContact2 = new Contact(FirstName='firstName3',
        lastName='lastName3',
        accountid = objAccount.Id);
       insert objContact2;
     
       // Retrieve data
       objAccount = [Select ID, Name  From Account WHERE ID = objAccount.Id];
       System.debug('Value after trigger fired: ' + objAccount.name);

       // Test that the trigger correctly updated the name for second contact
       System.assertEquals('lastName1, firstName1 and lastName3, firstName3',objAccount.name);
     
       // cover delete case
       delete objContact;
     
   
       / Retrieve data
       objAccount = [Select ID, Name  From Account WHERE ID = objAccount.Id];
       System.debug('Value after trigger fired: ' + objAccount.name);

       // Test that the trigger correctly updated the name on delete
       System.assertEquals('lastName3, firstName3',objAccount.name);
     
       // cover undelete case
       // Use all rows filter in soql to retrieve deleted record
       objContact = [SELECT Id FROM Contact WHERE Id =: objContact.Id ALL ROWS];
       undelete objContact;
     
       // Assert Account's Name field on undelete
        objAccount = [Select ID, Name  From Account WHERE ID = objAccount.Id];
       System.debug('Value after trigger fired: ' + objAccount.name);
      
       System.assertEquals('lastName1, firstName1 and lastName3, firstName3',objAccount.name);
     
       Test.stopTest();
    }
}
Rahul SharmaRahul Sharma
Try this-

//////////////////////////////////////////////////Code Start//////////////////////////////////////////////////
@isTest
private class TestAccountNameTrigger3 {
    static testMethod void validateAccountNameTrigger3() {
   
       Test.startTest();
      
       //create test data
       Account objAccount = new Account(Name='test',Client_Branch__c='Gold Coast');
       insert objAccount;
      
       // Cover insert case
       // Inserting a contact
       Contact objContact = new Contact(FirstName='firstName1',
        lastName='lastName1',
        accountid = objAccount.Id);
       insert objContact;
    
       // Retrieve data
       objAccount = [Select ID, Name  From Account WHERE Id = objAccount.Id];
       System.debug('Value after trigger fired: ' + objAccount.name);

       // Test that the trigger correctly updated the name
       System.assertEquals('lastName1, firstName1',objAccount.name);
    
       // Cover update case
       objContact = contact(FirstName='firstName2',lastName='lastName2',Id = objContact.Id);
       update objContact;
    
       // Assert Account's Name field on update
       System.assertEquals('lastName2, firstName2',objAccount.name);
     
       //Cover second insert
       Contact objContact2 = new Contact(FirstName='firstName3',
        lastName='lastName3',
        accountid = objAccount.Id);
       insert objContact2;
    
       // Retrieve data
       objAccount = [Select ID, Name  From Account WHERE ID = objAccount.Id];
       System.debug('Value after trigger fired: ' + objAccount.name);

       // Test that the trigger correctly updated the name for second contact
       System.assertEquals('lastName1, firstName1 and lastName3, firstName3',objAccount.name);
    
       // cover delete case
       delete objContact;
    
  
       // Retrieve data
       objAccount = [Select ID, Name  From Account WHERE ID = objAccount.Id];
       System.debug('Value after trigger fired: ' + objAccount.name);

       // Test that the trigger correctly updated the name on delete
       System.assertEquals('lastName3, firstName3',objAccount.name);
    
       // cover undelete case
       // Use all rows filter in soql to retrieve deleted record
       objContact = [SELECT Id FROM Contact WHERE Id =: objContact.Id ALL ROWS];
       undelete objContact;
    
       // Assert Account's Name field on undelete
        objAccount = [Select ID, Name  From Account WHERE ID = objAccount.Id];
       System.debug('Value after trigger fired: ' + objAccount.name);
     
       System.assertEquals('lastName1, firstName1 and lastName3, firstName3',objAccount.name);
    
       Test.stopTest();
    }
}

//////////////////////////////////////////////////Code end//////////////////////////////////////////////////
This was selected as the best answer
Developer.mikie.Apex.StudentDeveloper.mikie.Apex.Student
Still the same error:

Error: Compile Error: unexpected token: 'objAccount.Id' at line 19 column 62

I dont understand, we are clearly inserting the obj at

Account objAccount = new Account(Name='test',Client_Branch__c='Gold Coast');
       insert objAccount;



Would could be causing the problem..
Rahul SharmaRahul Sharma
Shit we missed out a colon in query.
Colon is required whenever we use variable in SOQL!

//////////////////////////////////////////////////Code Start//////////////////////////////////////////////////
objAccount = [Select ID, Name  From Account WHERE Id =: objAccount.Id];
//////////////////////////////////////////////////Code End//////////////////////////////////////////////////

Thanks,
Rahul
Developer.mikie.Apex.StudentDeveloper.mikie.Apex.Student
@isTest
private class TestAccountNameTrigger3 {
    static testMethod void validateAccountNameTrigger3() {
  
       Test.startTest();
     
       //create test data
       Account objAccount = new Account(Name='test',Client_Branch__c='Gold Coast');
       insert objAccount;
     
       // Cover insert case
       // Inserting a contact
       Contact objContact = new Contact(FirstName='firstName1',
        lastName='lastName1',
        accountid = objAccount.Id);
       insert objContact;
   
       // Retrieve data
       objAccount = [Select ID, Name  From Account WHERE Id =: objAccount.Id];
       System.debug('Value after trigger fired: ' + objAccount.name);

       // Test that the trigger correctly updated the name
       System.assertEquals('lastName1, firstName1',objAccount.name);
   
       // Cover update case
       objContact = contact(FirstName='firstName2',lastName='lastName2',Id = objContact.Id);
       update objContact;
   
       // Assert Account's Name field on update
       System.assertEquals('lastName2, firstName2',objAccount.name);
    
       //Cover second insert
       Contact objContact2 = new Contact(FirstName='firstName3',
        lastName='lastName3',
        accountid = objAccount.Id);
       insert objContact2;
   
       // Retrieve data
       objAccount = [Select ID, Name  From Account WHERE ID =: objAccount.Id];
       System.debug('Value after trigger fired: ' + objAccount.name);

       // Test that the trigger correctly updated the name for second contact
       System.assertEquals('lastName1, firstName1 and lastName3, firstName3',objAccount.name);
   
       // cover delete case
       delete objContact;
   
 
       // Retrieve data
       objAccount = [Select ID, Name  From Account WHERE ID =: objAccount.Id];
       System.debug('Value after trigger fired: ' + objAccount.name);

       // Test that the trigger correctly updated the name on delete
       System.assertEquals('lastName3, firstName3',objAccount.name);
   
       // cover undelete case
       // Use all rows filter in soql to retrieve deleted record
       objContact = [SELECT Id FROM Contact WHERE Id =: objContact.Id ALL ROWS];
       undelete objContact;
   
       // Assert Account's Name field on undelete
        objAccount = [Select ID, Name  From Account WHERE ID =: objAccount.Id];
       System.debug('Value after trigger fired: ' + objAccount.name);
    
       System.assertEquals('lastName1, firstName1 and lastName3, firstName3',objAccount.name);
   
       Test.stopTest();
    }
}


Each time I added a colon, it told me another variable did not exist further down. Then finally all the account SOQL colon'd and then I get the error:

Error: Compile Error: Variable does not exist: FirstName at line 26 column 29

I feel like we are soooo close, thank you so much for your help Rahul! I really appreciate it.

What could be causing it to not recognise 'Firstname'?
Developer.mikie.Apex.StudentDeveloper.mikie.Apex.Student
Ok, i dont know if I did it right...but my I added a 'new' tag at line 26 and it allowed me to save.

The test failed still, but I got code coverage of 82%.....I looked at the error and it said system assert = "etc" actual = "etc"...So i changed the system asssert to be the same as the actual, is that bad? Will it be detrimental to the system? I dont think it reads the update properly, as it does not change the system assert like it should.

regardless, the other system asserts were possibilities (as in it was either lastname1, firstname2 and lastname2, Firstname2 or vice versa) changed it and it passed 100%!!. 

This was the test code that passed 100%:

@isTest
private class TestAccountNameTrigger {
    static testMethod void validateAccountNameTrigger() {
  
       Test.startTest();
     
       //create test data
       Account objAccount = new Account(Name='test',Client_Branch__c='Gold Coast');
       insert objAccount;
     
       // Cover insert case
       // Inserting a contact
       Contact objContact = new Contact(FirstName='firstName1',
        lastName='lastName1',
        accountid = objAccount.Id);
       insert objContact;
   
       // Retrieve data
       objAccount = [Select ID, Name  From Account WHERE Id =: objAccount.Id];
       System.debug('Value after trigger fired: ' + objAccount.name);

       // Test that the trigger correctly updated the name
       System.assertEquals('lastName1, firstName1',objAccount.name);
      
        objContact = [Select ID, FirstName, LastName  From Contact WHERE Id =: objContact.Id];
   
       // Cover update case
   objContact = new Contact(LastName='lastName2',FirstName='firstname2',ID=objContact.id,AccountId=objAccount.Id);

       update objContact;
   
       // Assert Account's Name field on update
       System.assertEquals('lastName1, firstName1',objAccount.name);
    
       //Cover second insert
       Contact objContact2 = new Contact(FirstName='firstName3',
        lastName='lastName3',
        accountid = objAccount.Id);
       insert objContact2;
   
       // Retrieve data
       objAccount = [Select ID, Name  From Account WHERE ID =: objAccount.Id];
       System.debug('Value after trigger fired: ' + objAccount.name);

       // Test that the trigger correctly updated the name for second contact
       System.assertEquals('lastName3, firstName3 and lastName2, firstname2',objAccount.name);
   
       // cover delete case
       delete objContact;
   
 
       // Retrieve data
       objAccount = [Select ID, Name  From Account WHERE ID =: objAccount.Id];
       System.debug('Value after trigger fired: ' + objAccount.name);

       // Test that the trigger correctly updated the name on delete
       System.assertEquals('lastName3, firstName3',objAccount.name);
   
       // cover undelete case
       // Use all rows filter in soql to retrieve deleted record
       objContact = [SELECT Id FROM Contact WHERE Id =: objContact.Id ALL ROWS];
       undelete objContact;
   
       // Assert Account's Name field on undelete
        objAccount = [Select ID, Name  From Account WHERE ID =: objAccount.Id];
       System.debug('Value after trigger fired: ' + objAccount.name);
    
       System.assertEquals('lastName1, firstName1 and lastName3, firstName3',objAccount.name);
   
       Test.stopTest();
    }
}

Thank you so much for your help Rahul, I would not have gotten to where I am with the code without you and i have also learnt alot.

I was just wondering if you knew what I would have to add to the trigger to allow for Delete cases?
Rahul SharmaRahul Sharma
Great, Happy learning!!
Didn't get your last question, Please add a new question. We could try helping our best.

Thanks,
Rahul
Developer.mikie.Apex.StudentDeveloper.mikie.Apex.Student
I was just wondering what type of code should I add to the trigger which will make the name re-evaluate upon delete. At the moment it sort of works, but after I delete a contact, I have to wait until a field is edited within one of the remaiing contacts before the trigger strikes and re-writes the account name. Thank you Rahul.

Mikie