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
Edward PrignanoEdward Prignano 

Help writing a test class for two triggers

I have two triggers that I copied and pasted that work perfectly, but I don't know the first thing about writing a test class to move them in to production. Can anyone help out please? Here are my two triggers:
 
trigger QuoteCreator on Opportunity (after insert) {
for (Opportunity o : Trigger.new) {
Quote q = new Quote();
q.name = 'Quote-' + o.name;
q.opportunityId = o.id;
insert q;
}
}
 
trigger AddEquipment on Opportunity (before insert, after insert) {
    Pricebook2 standardBook = [SELECT Id FROM Pricebook2 WHERE IsStandard = true];
    if(Trigger.isBefore) {
        for(Opportunity record: Trigger.new) {
            record.Pricebook2Id = standardBook.Id;
        }
    }
    if(Trigger.isAfter) {
        OpportunityLineItem[] lines = new OpportunityLineItem[0];
        PricebookEntry entry = [SELECT Id, UnitPrice FROM PricebookEntry WHERE Pricebook2Id = :standardBook.Id AND Product2.ProductCode = 'L5000ADTLB'];
        for(Opportunity record: Trigger.new) {
            lines.add(new OpportunityLineItem(PricebookEntryId=entry.Id, OpportunityId=record.Id, UnitPrice=entry.UnitPrice, Quantity=1));
        }
        insert lines;
    }
    if(Trigger.isAfter) {
        OpportunityLineItem[] lines = new OpportunityLineItem[0];
        PricebookEntry entry = [SELECT Id, UnitPrice FROM PricebookEntry WHERE Pricebook2Id = :standardBook.Id AND Product2.ProductCode = '5816WMWH'];
        for(Opportunity record: Trigger.new) {
            lines.add(new OpportunityLineItem(PricebookEntryId=entry.Id, OpportunityId=record.Id, UnitPrice=entry.UnitPrice, Quantity=1));
        }
        insert lines;
    }
}

Thank you!
James LoghryJames Loghry
Hi Edward,

The first place you should go is the Apex Testing module on Trailhead: https://trailhead.salesforce.com/module/apex_triggers.  This module includes tips on testing triggers.

In a nutshell you test triggers by creating a unit test that inserts records around the object the triggers fire on.  Then, you use SOQL queries to verify the data is correct.

In your case, the unit test should create at least one opportunity (Ideally you would use a loop in your unit test to insert 200+ records for testing bulk loads).  Then you'd use SOQL to query and make sure the Quote and OpportunityLineItem records were created.

Hope that helps.
Edward PrignanoEdward Prignano
Thanks James... I did the following and it passed the test, but not sure if it accomplishes what it needs to though.
@isTest
public class QuoteCreatorTest {
    
    public static testMethod void QuoteCreatorTest(){
        Opportunity o = new Opportunity();
        o.Name = 'TestOpportunity';
        Quote q = new Quote();
		q.name = 'Quote-TestOpportunity';
    }
}


 
Edward PrignanoEdward Prignano
That didn't work... gave me a code coverage error
James LoghryJames Loghry
Nope, you'll need to insert the opportunity (call insert o; around line 7).  You can remove the Quote logic.  You'll also need to add some System.assert calls to verify that OpportunityLineItems and Quotes were created.  Check out the module I linked above, and it should help.
Lalit Mistry 21Lalit Mistry 21
Hi Edward,
Replace both the triggers with the one below (ideally you should have single trigger on object for better performance and better control on sequence of execution)
trigger OpportunityTrigger on Opportunity (before insert, after insert) {
	Id stdPricebook;
	if(System.Test.isRunningTest()){
		stdPricebook = System.Test.getStandardPricebookId();
	} else {
		Pricebook2 standardBook = [SELECT Id FROM Pricebook2 WHERE IsStandard = true];
		stdPricebook = standardBook.Id;
	}
    
    if(Trigger.isBefore) {
        for(Opportunity record: Trigger.new) {
            record.Pricebook2Id = stdPricebook;
        }
    }
    if(Trigger.isAfter) {
        OpportunityLineItem[] lines = new List<OpportunityLineItem>();
        Set<String> productCodes = new Set<String>{'L5000ADTLB', '5816WMWH'};
        List<PricebookEntry> entries = [SELECT Id, UnitPrice FROM PricebookEntry WHERE Pricebook2Id = :stdPricebook AND Product2.ProductCode IN :productCodes];
        
        for(PricebookEntry entry : entries){
            for(Opportunity record: Trigger.new) {
                lines.add(new OpportunityLineItem(PricebookEntryId=entry.Id, OpportunityId=record.Id, UnitPrice=entry.UnitPrice, Quantity=1));
            }       
        }

        insert lines;
        
        List<Quote> quotes = new List<Quote>();
        for (Opportunity o : Trigger.new) {
            Quote q = new Quote();
            q.name = 'Quote-' + o.name;
            q.opportunityId = o.id;
            quotes.add(q);
        }
        insert quotes;
    }
}

Once done, below test class can help you to get the required coverage.
@isTest
public class OppTriggerTest {
    
    public static testMethod void QuoteCreatorTest(){
        Opportunity opp = new Opportunity();
        opp.Name = 'TestOpportunity';
        opp.StageName = 'Prospecting';
        opp.CloseDate = System.today().addDays(20);
        System.Test.startTest();
        insert opp;
        System.Test.stopTest();
        List<Quote> quotes = [SELECT ID FROM Quote];
        System.assert(!quotes.isEmpty());
    }
}

That should solve your problem.
If that works, then mark this as an answer for benefit of others.