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
AmberTaylorAmberTaylor 

Write a test class for a trigger that update records

Hello, 

I need help Writting a test class since it's the first time i try it for real. I've done trailhead but i don't really see how it can apply to my trigger. 

Can someone can help me correct it and reach at least 75% of coverage code? I'm currently at 59%. 

Here is my Trigger : 
trigger UpdateCommune on Commune__c (before insert, before update) {
    //Store all Canton Codes in newly created records for Commune__c
    List<String> cantonCode = new List<String>();
    
    for (Commune__c a:Trigger.new){
        cantonCode.add(a.CodeCanton4Chiffres__c);
    }

    //Loop to update each Commune__c record with the proper CantonId__c
    List <Canton__C> CantonList = [Select ID, Name, CodeCanton4Chiffres__c from Canton__C where CodeCanton4Chiffres__c in :cantonCode];
    
    for (Integer i = 0; i <Trigger.new.size(); i++){
        if (CantonList.size() > 0 && Trigger.new[i].CodeCanton4Chiffres__c !=null){
            for (Canton__C c:CantonList){
                if (Trigger.new[i].CodeCanton4Chiffres__c == c.CodeCanton4Chiffres__c){
                    Trigger.new[i].CantonId__c = c.ID;
                  }
            }
        }
       else{
       Trigger.new[i].CantonId__c = null;
       System.System.debug('La référence Canton n\' pas pu être trouvée. Mise à jour impossible de la commune ');
        }
        
        // once the commune is updated with Canton ID, we need to update its "RegionAdministrative__c" fields regarding its "RegionCode__c" field value
    switch on Trigger.new[i].CodeRegion__c {
        when '82', '83' {
            Trigger.new[i].RegionAdministrative__c = 'AUVERGNE-RHONE-ALPES';
        }
        when '26', '43' {
            Trigger.new[i].RegionAdministrative__c = 'BOURGOGNE-FRANCHE-COMTE';
        }
        when '53' {
            Trigger.new[i].RegionAdministrative__c = 'BRETAGNE';
        }
        when '24' {
            Trigger.new[i].RegionAdministrative__c = 'CENTRE-VAL DE LOIRE';
        }
        when '94' {
            Trigger.new[i].RegionAdministrative__c = 'CORSE';
        }
        when '21','41', '42' {
            Trigger.new[i].RegionAdministrative__c = 'GRAND EST';
        }
        when '22', '31' {
            Trigger.new[i].RegionAdministrative__c = 'HAUTS-DE-FRANCE';
        }
        when  '11' {
            Trigger.new[i].RegionAdministrative__c = 'ILE-DE-FRANCE';
        }
        when '25', '23' {
            Trigger.new[i].RegionAdministrative__c = 'NORMANDIE';
        }        
        when '54', '74', '72' {
            Trigger.new[i].RegionAdministrative__c = 'NOUVELLE-AQUITAINE';
        }
        when '73', '91' {
            Trigger.new[i].RegionAdministrative__c = 'OCCITANIE';
        }
        when '52' {
            Trigger.new[i].RegionAdministrative__c = 'PAYS DE LA LOIRE';
        }
        when '93' {
            Trigger.new[i].RegionAdministrative__c = 'PROVENCE-ALPES-COTE D\'AZUR';
        }
    }
    }

}

Here is my Test Class : 
@isTest
private with sharing class UpdateCommune_TEST {
    private static testMethod void updateCommuneTEST() {
        // Create 2 Cantons then add them to a list that we will insert in Canton__c
        List<Canton__c> cantonList = new List<Canton__c>();

        Canton__c canton1 = new Canton__c(Name='Test Canton 2', CodeInseeCanton__c='12345', CodeCanton__c='01', CodeDepartement__c='12' );
        cantonList.add(canton1) ;
        Canton__c canton2 = new Canton__c(Name='Test Canton 2',  CodeInseeCanton__c='12543', CodeCanton__c='02', CodeDepartement__c='12' );
        cantonList.add(canton2) ;
        

        // Create 2 cities then add them to a list that we will insert in Commune__c
        List<Commune__c> communeList = new List<Commune__c>();
        Commune__c commune1 = new Commune__c(Name='Commune 1', CodeInseeCommune__c='12264', CodeDepartement__c='12', CodeCanton__c='01', CodeRegion__c='73');
        communeList.add(commune1);
        Commune__c commune2 = new Commune__c(Name='Commune 2', CodeInseeCommune__c='12265', CodeDepartement__c='12', CodeCanton__c='02', CodeRegion__c='73');
        communeList.add(commune2);
        
        test.startTest();
        insert cantonList;
        insert communeList;
        test.stopTest();

        // Retrieve the new communes
        List<Commune__c> createdCommunes = new List<Commune__c>([Select Name, Id, CodeInseeCommune__c, CodeDepartement__c, CodeCanton__c, CodeCanton4Chiffres__c, CodeRegion__c,Departement__c,CantonId__c, RegionAdministrative__c from Commune__c Where  CodeCanton4Chiffres__c='1201' OR CodeCanton4Chiffres__c='1202']);
       
        for (Integer i=0; i < createdCommunes.size(); i++) {
            System.debug('Value of canton after trigger fired: ' + createdCommunes[i].CantonId__c);
            // Test that the trigger correctly updated the RegionAdministrative
            System.assertEquals('OCCITANIE', createdCommunes[i].RegionAdministrative__c);
        }    
    }
}

Ty in advance for your help. 

 
Best Answer chosen by AmberTaylor
Christan G 4Christan G 4
Hi Amber, due to your switch extensive, you'll have to create at least one commune__c and canton__c objects for every possible field value that you specified within your switch. This should definitely increase your code coverage. Also, as a best practice, you should always write your code in a separate apex class and have a separate trigger that calls out to your class. This will make future enhancements much easier to implement if needed.

All Answers

Christan G 4Christan G 4
Hi Amber, due to your switch extensive, you'll have to create at least one commune__c and canton__c objects for every possible field value that you specified within your switch. This should definitely increase your code coverage. Also, as a best practice, you should always write your code in a separate apex class and have a separate trigger that calls out to your class. This will make future enhancements much easier to implement if needed.
This was selected as the best answer
AmberTaylorAmberTaylor
Hello Christian, Ty very much for your quick answer. 
I modified my code and succeed in writting a test class with full coverage. 
For the Switch part, I used a process builder instead of hard coding it in the trigger. 

The point is, how can I put the trigger code in a class? (You'll see bellow what I started to do) : 

Here is my updated trigger : 
trigger UpdateCommune on Commune__c (before insert, before update) {
    
    for(Commune__c c: Trigger.new) {
        if (c.CodeCanton4Chiffres__c != null) {
            UpdateCommune.UpdateCommuneWithCantonID(Trigger.new);
        }
    }
}

Here is My trigger class :
public with sharing class UpdateCommune {
    public static void UpdateCommuneWithCantonID(List<Commune__c> communesList) {
        //Store all Canton Codes for newly created records in cantonCode variable
        List<String> cantonCode = new List<String>();
        for (Commune__c c : communesList) {
            cantonCode.add(c.CodeCanton4Chiffres__c);
        }

        //Loop to update each Commune__c record with the proper CantonId__c
        List <Canton__C> CantonList = [Select ID, Name, CodeCanton4Chiffres__c from Canton__C where CodeCanton4Chiffres__c in :cantonCode];

        for (Integer i = 0; i < communesList.size(); i++){
            if (CantonList.size() > 0 /*&& Trigger.new[i].CodeCanton4Chiffres__c !=null*/){
                for (Canton__C c:CantonList){
                    if (communesList[i].CodeCanton4Chiffres__c == c.CodeCanton4Chiffres__c){
                        communesList[i].CantonId__c = c.ID;
                      } else{
                        communesList[i].CantonId__c = null;
                        System.System.debug('La référence Canton n\' pas pu être trouvée. Mise à jour impossible de la commune ');
                    }
                }
            } 
        }
    }
}

Here is my test class :
@isTest
private with sharing class UpdateCommune_TEST {

    @isTest static void testUpdatingCommune() {
        // First, we create 2 Cantons then add them to a list that we will insert in Canton__c
        List<Canton__c> cantonList = new List<Canton__c>();

        Canton__c canton1 = new Canton__c(Name='Test Canton 1', CodeInseeCanton__c='12345', CodeCanton__c='01', CodeDepartement__c='12' );
        cantonList.add(canton1) ;
        Canton__c canton2 = new Canton__c(Name='Test Canton 2',  CodeInseeCanton__c='12543', CodeCanton__c='02', CodeDepartement__c='12' );
        cantonList.add(canton2) ;

        insert cantonList;

        //Then I create a commune that should be automatically linked to my newly created newCanton
        Commune__c newCommune = new Commune__c();
        newCommune.Name='Commune 2';
        newCommune.CodeInseeCommune__c='12265';
        newCommune.CodeDepartement__c='12';
        newCommune.CodeCanton__c='02';
        newCommune.CodeRegion__c='73';
        insert newCommune;

        //I need to test the update part, to check is my commune is related to my newCanton2
        newCommune.Name='Commune 1';
        newCommune.CodeCanton__c='01';
        newCommune.CodeRegion__c='93';
        update newCommune;

        System.debug('newCommune updated value = ' + newCommune);
    }
}

After addi​​​​​​​ng the class for the trigger, I still have 100% Code Coverage for both trigger and class. I already checked if the update was ok on records and it was. 

Do I need to implement a handler class for the trigger, for future developpements ? or it can stay this way ?