+ Start a Discussion
AntonPavlovAntonPavlov 

write a trigger test

This is code trriger
trigger changeFieldProduct on Product2 (after insert,after update) { 
    List<Task> taskList = new List<Task>();
    for(Product2 prod: Trigger.New){
        if(prod.IsActive__c == false){
         List<OpportunityLineItem> obj = [SELECT OpportunityId,Opportunity.Account.Phone, Product2Id FROM OpportunityLineItem WHERE Product2Id=:prod.id];
            for(OpportunityLineItem  opp :obj){
                 taskList.add(new Task(
                                    Subject='new',
                                    whatId = opp.OpportunityId,
                                       Status='New',
                                    Auto_Created__c=true,
                                    ActivityDate = date.today,
                                    Phone__c = opp.Opportunity.Account.Phone,
                                    Priority = 'High'));
            }
        }
   }
    if(taskList.size()>0){
        insert taskList;
    }
}
Test class write only to 40% but I need get 100% help to solve 

@isTest
public class changeFieldProductTest {
@isTest
    public static void testing(){
       List<Task> taskList = new List<Task>();
       List<Product2> prod = new List<Product2>();
        for(Integer i=0;i<10;i++){
           Product2 p = new Product2(Name='test ' +i, IsActive__c = false);
            prod.add(p);
        }
        Test.startTest();
            insert prod;
        Test.stopTest();
        
       System.assertEquals(10, prod.size()); 
        
       List<OpportunityLineItem> obj = [SELECT OpportunityId,Opportunity.Account.Phone, Product2Id FROM OpportunityLineItem WHERE Product2Id IN:prod];
       
       System.assertEquals(10, prod.size());
    }
}
Best Answer chosen by AntonPavlov
Maharajan CMaharajan C
Hi Uladzimir,

Please use try the below updated trigger and Test Class.

In test class if any required fields are missing then add it to create the records. Add the system asserts in test class.


Apex Trigger :
trigger changeFieldProduct on Product2 (after insert,after update) { 
    List<Task> taskList = new List<Task>();
	set<Id> prodIds = new set<Id>();
    for(Product2 prod: Trigger.New){
        if(prod.IsActive__c == false){
			prodIds.add(prod.id);
        }
    }
	
	if(!prodIds.IsEmpty()){
		List<OpportunityLineItem> obj = [SELECT OpportunityId,Opportunity.Account.Phone, Product2Id FROM OpportunityLineItem WHERE Product2Id IN: prodIds];
		for(OpportunityLineItem  opp :obj){
			 taskList.add(new Task(
								Subject='new',
								whatId = opp.OpportunityId,
                 				Status='New',
								Auto_Created__c=true,
								ActivityDate = Date.today(),
								Phone__c = opp.Opportunity.Account.Phone,
								Priority = 'High'));
        }
	}
	
    if(taskList.size()>0){
        insert taskList;
    }
}

Test Class:
 
@isTest
public class changeFieldProductTriggerTest {
    @isTest static void changeFieldProductTest(){
        Account acc = new Account(Name = 'Test Account');
        insert acc;
        
        opportunity opp = new opportunity(Name='Test Account Opp' ,  AccountId= acc.Id,StageName = 'Prospecting', 
                                   CloseDate = Date.today() + 30);
        insert opp;
        
        Id pricebookId = Test.getStandardPricebookId();

        Product2 prod = new Product2(
            Name = 'Product X',
            ProductCode = 'Pro-X',
            isActive = true,
            IsActive__c = true
        );
        insert prod;
        
        PricebookEntry pbEntry = new PricebookEntry(
            Pricebook2Id = pricebookId,
            Product2Id = prod.Id,
            UnitPrice = 100.00,
            IsActive = true
        );
        insert pbEntry;
        
        OpportunityLineItem oli = new OpportunityLineItem(
            OpportunityId = opp.Id,
            Quantity = 5,
            PricebookEntryId = pbEntry.Id,
            TotalPrice = 5 * pbEntry.UnitPrice,
            Product2Id = prod.Id
        );
        insert oli;
        
        Test.startTest();
        	prod.IsActive__c = false;
        	update prod;
        Test.stopTest();
    }
}

Thanks,
Maharajan.C

All Answers

ANUTEJANUTEJ (Salesforce Developers) 
Hi Uladzimir,

I would suggest you to remove the soql from the for loop as it might lead to reaching of governer limit and also, I see that the for loop is not being covered because there are no opportunities that are inserted so no list of opportunity records are retrieved and the for loop is not being covered, so the changes you need to make are as follows:

>> remove the soql from inside for loop you can run the for loop by creating a map of produced and list of opportunity records and then fetching these records using get.

>> As the product records are new you need to insert respective opportunity records so as to cover the nested for loop i.e., to cover the below part:
 
taskList.add(new Task(
                                    Subject='new',
                                    whatId = opp.OpportunityId,
                                       Status='New',
                                    
                                    ActivityDate = date.today(),
                                    
                                    Priority = 'High'));
            }

Let me know if it helps you and close your query by marking it as solved so that it can help others in the future.  

Thanks.
AntonPavlovAntonPavlov
I try to do like you but it is not work .I khow that it is bad practic use soql  request to loop but I dont now how fix this.
Maharajan CMaharajan C
Hi Uladzimir,

Please use try the below updated trigger and Test Class.

In test class if any required fields are missing then add it to create the records. Add the system asserts in test class.


Apex Trigger :
trigger changeFieldProduct on Product2 (after insert,after update) { 
    List<Task> taskList = new List<Task>();
	set<Id> prodIds = new set<Id>();
    for(Product2 prod: Trigger.New){
        if(prod.IsActive__c == false){
			prodIds.add(prod.id);
        }
    }
	
	if(!prodIds.IsEmpty()){
		List<OpportunityLineItem> obj = [SELECT OpportunityId,Opportunity.Account.Phone, Product2Id FROM OpportunityLineItem WHERE Product2Id IN: prodIds];
		for(OpportunityLineItem  opp :obj){
			 taskList.add(new Task(
								Subject='new',
								whatId = opp.OpportunityId,
                 				Status='New',
								Auto_Created__c=true,
								ActivityDate = Date.today(),
								Phone__c = opp.Opportunity.Account.Phone,
								Priority = 'High'));
        }
	}
	
    if(taskList.size()>0){
        insert taskList;
    }
}

Test Class:
 
@isTest
public class changeFieldProductTriggerTest {
    @isTest static void changeFieldProductTest(){
        Account acc = new Account(Name = 'Test Account');
        insert acc;
        
        opportunity opp = new opportunity(Name='Test Account Opp' ,  AccountId= acc.Id,StageName = 'Prospecting', 
                                   CloseDate = Date.today() + 30);
        insert opp;
        
        Id pricebookId = Test.getStandardPricebookId();

        Product2 prod = new Product2(
            Name = 'Product X',
            ProductCode = 'Pro-X',
            isActive = true,
            IsActive__c = true
        );
        insert prod;
        
        PricebookEntry pbEntry = new PricebookEntry(
            Pricebook2Id = pricebookId,
            Product2Id = prod.Id,
            UnitPrice = 100.00,
            IsActive = true
        );
        insert pbEntry;
        
        OpportunityLineItem oli = new OpportunityLineItem(
            OpportunityId = opp.Id,
            Quantity = 5,
            PricebookEntryId = pbEntry.Id,
            TotalPrice = 5 * pbEntry.UnitPrice,
            Product2Id = prod.Id
        );
        insert oli;
        
        Test.startTest();
        	prod.IsActive__c = false;
        	update prod;
        Test.stopTest();
    }
}

Thanks,
Maharajan.C
This was selected as the best answer
AntonPavlovAntonPavlov
Hi Maharajan.C, Thanks for the help everything works fine. I am very grateful to you.