+ Start a Discussion
alexjalexj 

Problem with test trigger

I have created a trigger with test a trigger after insert. 

The problem is that the trigger run on the initialization of leads and accounts and don't run on insert which is between test.startTest et test.stopTest.

 

@isTest
public class TestinsertLead {
    static testMethod void TestInsertListLead(){
    
    //initialisation des variables
    List <Lead> ld = new List<Lead>();
    List <Account> acc = new List<Account>();
    for(integer i = 0; i<2; i++){
        Lead lead = new Lead(
        Salutation = 'M.',
        FirstName ='Hélène',
        LastName = 'test',
        Adresse_mail__c = 'test'+i+'@mail.com',//test0@mail.com, test1@mail.com
        LeadSource = 'Newsletter',
        Origine_connaissance_Kiwatch__c ='',
        Num_ro_piste__c = 0,     
        demande__c = 'par mail',
        Demande_contact__c = 'demande',
        Objet_demande__c = 'objet');
        
        ld.add(lead);
    } 

       for(integer i = 2; i<4; i++){
           Account account= new Account(
            Salutation = '',
            FirstName ='',
            LastName = 'test',
            Adresse_mail__c = 'test'+i+'@mail.com',//test2@mail.com, test3@mail.com
            PersonLeadSource = 'Newsletter',
            Numero_client__c = 0,            
            Demande_contact__c = 'sdkljfqsd',
            Objet_demande__c = 'sdfklsqfdkjs',
            Raison_fin_de_contrat__c ='',
            Abonnement__c='Pro');
            
            acc.add(account);
        }              
            
    insert ld;System.debug('insert of init leads ok');
    insert acc;System.debug('insert of init accounts ok');
   
            
    //début du test 
    Test.startTest(); 
    List <Lead> newLeads= new List<Lead>();
    for(integer i = 1; i<3; i++){
        Lead lead = new Lead(
        Salutation = 'M.',
        FirstName ='Hélène',
        LastName = 'test',
        Adresse_mail__c = 'test'+i+'@mail.com',//test1@mail.com, test2@mail.com
        LeadSource = 'Newsletter',
        Origine_connaissance_Kiwatch__c ='',
        Num_ro_piste__c = 0,  
        demande__c = 'par mail',
        Demande_contact__c = 'demande',
        Objet_demande__c = 'objet');
        
        newLeads.add(lead);
    } 
        
    insert newLeads;System.debug('insert of test  leads ok');
    Test.stopTest() ;
    
    
    }
}

 When I display debug, I see :

|DEBUG|insert piste : test0@mail.com
|DEBUG|insert piste : test1@mail.com
|DEBUG|insert of init leads ok
|DEBUG|insert of init accounts ok
|DEBUG|insert of test leads ok

 

 

alexjalexj

I thought have result my problem by activating one trigger (trigger after insert Lead and trigger after insert Account). It work on Sandbox to test the coverage.

The problem is that I can't deploy because when my two trigger is activating, the code isn't correctly covered.

 

How can I activate my two trigger and test one after the other ?

Alex.AcostaAlex.Acosta

What exception are you getting when you're trying to deploy? Also this is a bit hard to test without seeing or explaining what your trigger is doing... I can give you guesses. 

alexjalexj

I have no exception. The problem is that the code isn't covered to 75 %.

My trigger enable to verify if there already  is a lead (or an acocunt) with the same email and if it's the case, merge the way.

When I test myself the trigger by directly inserting account or lead on sandbox, the trigger run correctly. 

 

Here a part of my trigger :

 

trigger triggerAfterInsertLead on Lead (after insert ) {
    if(checkRecursive.runOnce())
    {
        Set<String> leadmail = new Set<String>();// liste des nouvelles pistes (par email)
        List<Lead> updatedLead = new List<Lead>();
        List<Account> updatedAccount = new List<Account>();
        List<Lead> deletedLead = new List<Lead>();
        String demande ='';
        boolean existingAccount = false;
        String URL = ' https://cs16.salesforce.com/';
        
        for (Lead l : trigger.new)// ajout des nouveaux id
        {
            leadmail .add(l.Adresse_mail__c);
            System.debug('tentative d\'insertion de la piste :'+l.Adresse_mail__c);
        }
        
        //récupération pistes et comptes existants
        List<Lead> leads = [SELECT  Id, Salutation, FirstName , Adresse_mail__c, LastName, Num_ro_piste__c, LeadSource,Phone, Telephone_portable__c, Rating,Type_d_utilisation__c , Origine_connaissance_Kiwatch__c, Client__c, D_sinscription_la_newsletter__c, Inscription_la_newsletter__c, Raison_de_la_d_sinscription__c, Date_de_d_sinscription_la_newsletter__c, Date_d_inscription_la_newsletter__c, Street, City, State, Country, PostalCode, accepte_jeux__c, Date_inscription_au_jeu__c, Email_parr__c, Email_parrainage_2__c, Email_parrainage_3__c, Email_parrainage_4__c, Email_parrainage_5__c  from Lead /*where id in: ids*/];
        List<Account>accounts = [SELECT Id , Salutation, FirstName , Adresse_mail__c, LastName, PersonLeadSource, Numero_client__c, D_sinscription_la_newsletter__c, Inscription_la_newsletter__c, Raison_de_la_d_sinscription__c, Date_de_d_sinscription_la_newsletter__c, Date_d_inscription_la_newsletter__c  FROM Account] ;

        existingAccount = false;
        
        for (Lead lnew : trigger.new)
        {        
            for(Account acc : accounts)
            {
                if(acc.Adresse_mail__c == lnew.Adresse_mail__c){
                    existingAccount = true;
                    
//merge fields ...     					
                   
                    updatedAccount.add(acc);
                    deletedLead.add(lnew);
                }              
            }
            for (Lead ld : leads)
            {
                if(ld.Id == lnew.Id)
                {
                    System.debug('Id egal'+ ' '+ld.Id+ ' '+lnew.Id);
                }
                else if(ld.Adresse_mail__c == lnew.Adresse_mail__c)
                {
                    System.debug('piste existante; mail : '+ + ld.Adresse_mail__c+ ' ld Id : '+ld.Id+ ' lnew Id : '+lnew.Id);
                    if(!existingAccount){                 
                        
//merge fields ...                    
                        updatedLead.add(ld);
                        deletedLead.add(lnew);
                    }
                    else
                        deletedLead.add(ld); 
                }
            }    
        }
		
        if(updatedLead.size()>0){
            System.debug('mise à jour des pistes');
            update updatedLead;
        }
        
        if(updatedAccount.size()>0){
            System.debug('mise à jour comptes');
            update updatedAccount;
        }

        if(deletedLead.size()>0){
            for (Lead l : deletedLead){
                System.debug('suppression des pistes'+l.Adresse_mail__c);
                MyFutureClass.DeleteLead(l.Id);
            }

        }
    }

}

 

Alex.AcostaAlex.Acosta

I already see a few problems with your trigger.

1) Issues once your org gets big enough you'll have to have limits on records you are pulling back

2) Executed Lines Script exception (once you pass 200k)

 

You can make this a lot simpler just by removing your multiple nested loops and using your set<String> which is your email address to query for exising leads IE:

 

List<Lead> leads = [SELECT  Id, Salutation, FirstName , Adresse_mail__c, LastName, Num_ro_piste__c, LeadSource,Phone, Telephone_portable__c, Rating,Type_d_utilisation__c , Origine_connaissance_Kiwatch__c, Client__c, D_sinscription_la_newsletter__c, Inscription_la_newsletter__c, Raison_de_la_d_sinscription__c, Date_de_d_sinscription_la_newsletter__c, Date_d_inscription_la_newsletter__c, Street, City, State, Country, PostalCode, accepte_jeux__c, Date_inscription_au_jeu__c, Email_parr__c, Email_parrainage_2__c, Email_parrainage_3__c, Email_parrainage_4__c, Email_parrainage_5__c  from Lead WHERE Address_mail__c IN :leadmail]; 

This concept should be used on your accounts as well.

 

Once you're done getting back your records put them in a map if you'd like and use the key to hold emails.

Map<String,Lead> leadMap = new Map<String,Lead>();

// fill up map
for(Lead lead :leads){
   leadMap.put(lead.address_mail__c, lead);
}

// validate if any leads have the same email address
for(Lead lead :trigger.new){
    if(null != lead.address_mail__c && leadMap.containsKey(lead.address_mail__c){
         //do merge
    }
if(null != lead.address_mail__c && accountMap.containsKey(lead.address_mail__c){
//do merge
} }

 Again use this concept to check out your accounts and do any mapping you need.

 

Also this should make you cover your test cases a lot easier.

 

Last thing, and this is just personal preference is add the annotation parameter @isTest(SeeAllData=false). Just because records could already exist that may screw up what you are testing.

 

alexjalexj

OK,

What is the interrest to use a Map ?

I have modified my trigger but there always only 52% of code covered

 

trigger triggerAfterInsertLead on Lead (after insert ) {

    if(checkRecursive.runOnce())
    {
        Set<String> leadmail = new Set<String>();// liste des nouvelles pistes (par email)
        List<Lead> updatedLead = new List<Lead>();
        List<Account> updatedAccount = new List<Account>();
        List<Lead> deletedLead = new List<Lead>();
        String demande ='';
        boolean existingAccount = false;
        String URL = ' https://cs16.salesforce.com/';
        
        for (Lead l : trigger.new)// ajout des nouveaux id
        {
            leadmail .add(l.Adresse_mail__c);
            System.debug('tentative d\'insertion de la piste :'+l.Adresse_mail__c);
        }
        
        //récupération pistes et comptes existants

        List<Lead> leads = [SELECT  Id, Salutation, FirstName , Adresse_mail__c, LastName, Num_ro_piste__c, LeadSource,Phone, Telephone_portable__c, Rating,Type_d_utilisation__c , Origine_connaissance_Kiwatch__c, Client__c, D_sinscription_la_newsletter__c, Inscription_la_newsletter__c, Raison_de_la_d_sinscription__c, Date_de_d_sinscription_la_newsletter__c, Date_d_inscription_la_newsletter__c, Street, City, State, Country, PostalCode, accepte_jeux__c, Date_inscription_au_jeu__c, Email_parr__c, Email_parrainage_2__c, Email_parrainage_3__c, Email_parrainage_4__c, Email_parrainage_5__c  from Lead WHERE Adresse_mail__c IN :leadmail]; 
        List<Account>accounts = [SELECT Id , Salutation, FirstName , Adresse_mail__c, LastName, PersonLeadSource, Numero_client__c, D_sinscription_la_newsletter__c, Inscription_la_newsletter__c, Raison_de_la_d_sinscription__c, Date_de_d_sinscription_la_newsletter__c, Date_d_inscription_la_newsletter__c  FROM Account WHERE Adresse_mail__c IN :leadmail] ;
  
         Map<String,Lead> leadMap = new Map<String,Lead>();
         Map<String,Account> accountMap = new Map<String,Account>();

        // fill up map
        for(Lead lead :leads){
           leadMap.put(lead.Adresse_mail__c, lead);
        }
        for(Account account :accounts){
           accountMap.put(account.Adresse_mail__c, account);
        }

        // validate if any leads have the same email address
        for(Lead lnew :trigger.new){     
            
            if(null != lnew.Adresse_mail__c && leadMap.containsKey(lnew.Adresse_mail__c) && (leadMap.get(lnew.Adresse_mail__c).Id !=lnew.Id)){
                Lead ld = leadMap.get(lnew.Adresse_mail__c);

                if(ld.Salutation == null){ld.Salutation = lnew.Salutation;}
                if(ld.FirstName == null){ld.FirstName = lnew.FirstName;}
                ...
            
                updatedLead.add(ld);
                deletedLead.add(lnew);
            }
            
            if(null != lnew.Adresse_mail__c&& accountMap.containsKey(lnew.Adresse_mail__c)){
                Account acc = accountMap.get(lnew.Adresse_mail__c);
                if(acc.Salutation == null){acc.Salutation = lnew.Salutation;}
                if(acc.FirstName == null){acc.FirstName = lnew.FirstName;}
                ...   
                                 
                updatedAccount.add(acc);
                deletedLead.add(lnew);
            }            
        }

        if(updatedLead.size()>0){
            System.debug('mise à jour des pistes');
            update updatedLead;
        }
        
        if(updatedAccount.size()>0){
            System.debug('mise à jour comptes');
            update updatedAccount;
        }

        if(deletedLead.size()>0){
            for (Lead l : deletedLead){
                System.debug('suppression des pistes'+l.Adresse_mail__c);
                MyFutureClass.DeleteLead(l.Id);
            }

        }

    }
}

 

alexjalexj

And my test class is : 

@isTest
public class TestinsertLead {
    static testMethod void TestInsertWithLead(){
    
    //initialisation des variables
    List <Lead> ld = new List<Lead>();
  
    for(integer i = 0; i<2; i++){
        Lead lead = new Lead(
        Salutation = 'M.',
        FirstName ='Hélène',
        LastName = 'test',
        Adresse_mail__c = 'test@mail.com',
        LeadSource = 'Newsletter');
        
        ld.add(lead);
    }     
       insert ld;   System.debug('insertion des pistes initiales ok');
    
    }
    
     static testMethod void TestInsertWithAccount(){
     
        List <Account> acc = new List<Account>();
        for(integer i = 0; i<2; i++){
           Account account= new Account(
            Salutation = '',
            FirstName ='',
            LastName = 'test',
            Adresse_mail__c = 'test'+i+'@mail.com',
            PersonLeadSource = 'Newsletter');
            
            acc.add(account);
        }              
            
 
    insert acc;     System.debug('insertion des comptes initiaux ok');
               
    //début du test 
    Test.startTest(); system.debug('start test');
    List <Lead> newLeads= new List<Lead>();
    for(integer i = 0; i<2; i++){
        Lead lead = new Lead(
        Salutation = 'Melle',
        FirstName ='Hélène',
        LastName = 'test',
        Adresse_mail__c = 'test'+i+'@mail.com',
        LeadSource = 'Newsletter');
        
        newLeads.add(lead);
    } 
        
    insert newLeads;System.debug('insertion des leads test ok');
    Test.stopTest() ;
     }
}

 

Alex.AcostaAlex.Acosta

The reason for the map is later on your trigger could hit govenor limits due to the loops previously  and amount records being pulled back. Thats why I suggested that. As far as your code, the only thing that looks like you are not hitting is your merge conditions. Is this correct?

 

if(ld.Salutation == null){ld.Salutation = lnew.Salutation;} 

 

This tells me that it will only go inside and copy the same field content if the value is null. Because of this you're not getting inside your IF statements. If this isn't it. Can you please point out which lines of code you are not hitting?

alexjalexj

Indeed, some field are unmodifiable (like Salutation) when there are already filled.

Other are modifiable :

 

  //champs identification de la piste (non modifiable)
                    if(acc.Salutation == null){acc.Salutation = lnew.Salutation;}
                    if(acc.FirstName == null){acc.FirstName = lnew.FirstName;}
                    if(acc.LastName == null){acc.LastName = lnew.LastName;} 
                    
                 
                    //information sur l'adresse. Si un est modifié, tous le sont
                    if(lnew.Street !=null || lnew.City !=null || lnew.PostalCode !=null || lnew.Country !=null || lnew.State !=null)
                    {
                       acc.PersonMailingStreet = lnew.Street;
                       acc.PersonMailingCity = lnew.City ;
                       acc.PersonMailingPostalCode = lnew.PostalCode;
                       acc.PersonMailingCountry = lnew.Country;
                       acc.PersonMailingState = lnew.State ;
                    }
        
                    if(lnew.Phone !=null){acc.PersonHomePhone = lnew.Phone ;}
                    if(lnew.Telephone_portable__c !=null){acc .PersonMobilePhone =  lnew.Telephone_portable__c ;}          
                    if(lnew.Rating !=null){acc .Rating = lnew.Rating ;}
                    if(lnew.Company ==null){acc.Soci_t__c = lnew.Company;}

 I don't think that the problem is the trigger because when I test myself by inserting lead directly on sandbox, it's run correctly. I think that the probleme is the test class by I don't understand why the trigger don't run for the second insert. 

alexjalexj

up please 

Anybody knows why my trigger don't run when I call it a second time ?