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
FGNYFGNY 

Test Class for a simple trigger

Hello,

Despite creating S-Controls for our organization for several years we just started to create our first Apex Triggers and immediatly run into the "Test Classes"-problem. We created the following simple trigger which is working in the Sandbox but cannot transfer it to Production Environment without a Test Class.

 

When a user tries to set the Opportunity Stage to "Won", the trigger checks if there is a quotation file among opportunity attachments and if not, prevents saving the record with an error message. Here is the code:

 

trigger CheckOppAttachments on Opportunity (before update) 
{
    if (trigger.new[0].StageName == 'Closed Won')
    {
        Boolean pdf = false;
        Boolean pdfloop = false;
    
        Opportunity opp = trigger.new[0];
        Attachment[] atts = [SELECT Name FROM Attachment WHERE ParentId =: opp.Id];
        for (Integer i = 0; i < atts.size(); i++) 
        {
            pdfloop = atts[i].Name.contains(opp.Quotation_No__c);
            if (pdfloop)
            {
            pdf=true;
	    }
        }
		
	if (pdf)
	{}
	else
	{
	     opp.addError('The Stage can not be set to "Won" as long Quotation is not attached');
	}
    }
}   

 

Any example of a test class for such a trigger would be appreciated.

 

 

 

 

Best Answer chosen by Admin (Salesforce Developers) 
AmitSahuAmitSahu

@isTest
private class Tmethod {
static testMethod void UnitTest(){
Opportunity lstOpp = new Opportunity(Name='testopp',stage='Open');
insert lstOpp;
lstOpp.Stage='Closed Won';
Update lstOpp;
}
}


This can be a starting point

All Answers

AmitSahuAmitSahu

@isTest
private class Tmethod {
static testMethod void UnitTest(){
Opportunity lstOpp = new Opportunity(Name='testopp',stage='Open');
insert lstOpp;
lstOpp.Stage='Closed Won';
Update lstOpp;
}
}


This can be a starting point

This was selected as the best answer
FGNYFGNY

Many thanks for your help, we just had to slightly extend your code (creation of account and opp with required values) and it worked immediatly. Unfortunately after executing the test the code coverage displayed is 68%, while at least 75% are necessary do deploy. The message displayed is

System.DmlException: Update failed. First exception on row 0 with id 006M0000004Sq74IAC; first error: FIELD_CUSTOM_VALIDATION_EXCEPTION, The Stage can not be set to "Won" as long Quotation is not attached: []

 which is exaclty the desired error message the trigger should produce when the file is not attached. However this prevents the code from being deployment. Here is the test code after the necessary modifications

 

@isTest
private class TestCheckOppAtt 
{
static testMethod void UnitTest()
{	
Account testAcc = new Account(Name='testacc', Key_Account__c='<No>', Country__c='Germany', ShippingCity='Berlin', Main_Region__c='EU', Sub_Region__c='Ger', Business_Unit__c='ME', Industry='Steel');
Opportunity testOpp = new Opportunity(Name='testopp', StageName='Prospecting', AccountId=testAcc.Id, Business_Unit__c='ME', Location__c='AAC', SalesChannel__c='direct', NextStep='Sleeping', Gross_Margin__c=15, CloseDate=Date.today(), Est_Delivery_Date__c=Date.today());
Insert testOpp;
testOpp.StageName='Closed Won';
Update testOpp;
}
}

 

 After some googling it seems the test has to cover both cases: when an opportunity has the files and the case when it hasn't. But it seems impossible to create files and attach them with APEX. Is it possible to update existing opportunities with a test class instead of creating new? I tried but it did not worked.

Is there an other possibility to rework the test class or the trigger code to reach 75%?

AmitSahuAmitSahu
yes, once you insert the opportunity record you will get the Id and the you create new attachment object and link to the same id you got from the previous insert operation.
FGNYFGNY

Thank you very much for your help, with your hint I managed to get 100% coverage with the following code.

 

@isTest
private class TestCheckOppAtt
{
static testMethod void UnitTest()
{
Account testAcc = new Account(Name='testacc', Key_Account__c='<No>', Country__c='Germany', ShippingCity='Berlin', Main_Region__c='EU', Sub_Region__c='Ger', Business_Unit__c='ME', Industry='Steel');
Insert testAcc;
Opportunity testOpp = new Opportunity(Name='testopp', StageName='Prospecting', AccountId=testAcc.Id, Business_Unit__c='ME', Location__c='AAC', SalesChannel__c='direct', NextStep='Sleeping', Gross_Margin__c=15, Quotation_No__c='AAC0811EST022916', CloseDate=Date.today(), Est_Delivery_Date__c=Date.today());
Insert testOpp;
Attachment testpdf = new Attachment(Name='AAC0811EST022916_Quotation.pdf', ParentId=testOpp.Id, Body = Blob.valueOf('AAC0811EST022916_Quotation.pdf'));
Insert testpdf;
Insert testdat;
testOpp.StageName='Closed Won';
Update testOpp;
testOpp.StageName='Prospecting';
Update testOpp;
Delete testpdf;
testOpp.StageName='Closed Won';
Update testOpp;
}

 

However I still can't deploy it because despite 100% coverage the test run ends with a failure and the message

System.DmlException: Update failed. First exception on row 0 with id 006M0000004Sq7mIAC; first error: FIELD_CUSTOM_VALIDATION_EXCEPTION, The Stage can not be set to "Probable" as long Quotation is not attached to the Opportunity: []

So the actually desired error message prevents the trigger from being deployed.

Is the method "addError('');" therefore unusable in Production environment?

Is there a way to circumvent it?

FGNYFGNY

OK, the solution for the last problem was to use try/catch.

The following test class finally delivers 100% without a failure.

@isTest
private class TestCheckOppAtt 
{
static testMethod void UnitTest()
{
Account testAcc = new Account(Name='testacc', Key_Account__c='<No>', Country__c='Germany', ShippingCity='Berlin', Main_Region__c='EU', Sub_Region__c='Ger', Business_Unit__c='ME', Industry='Steel');
Insert testAcc;
Opportunity testOpp = new Opportunity(Name='testopp', StageName='Prospecting', AccountId=testAcc.Id, Business_Unit__c='ME', Location__c='AAC', SalesChannel__c='direct', NextStep='Sleeping', Gross_Margin__c=15, Quotation_No__c='AAC0811EST022916', CloseDate=Date.today(), Est_Delivery_Date__c=Date.today());
Insert testOpp;
Attachment testpdf = new Attachment(Name='AAC0811EST022916_Quotation.pdf', ParentId=testOpp.Id, Body = Blob.valueOf('AAC0811EST022916_Quotation.pdf'));
Attachment testdat = new Attachment(Name='Calc.dat', ParentId=testOpp.Id, Body = Blob.valueOf('Calc.dat'));
Insert testpdf;
Insert testdat;
testOpp.StageName='Probable';
Update testOpp;
testOpp.StageName='Prospecting';
Update testOpp;
Delete testpdf;
try
{
testOpp.StageName='Probable';
Update testOpp;
}
catch (Exception e)
{
}

}
}

 Many thanks to j020, without your help test classes would still be forbidden land for me.

AmitSahuAmitSahu
You can disable the validation rule while deploying . Once deployed you can enable the rule again.. -- Amit Kumar Sahu