+ Start a Discussion

Help on test class to get maximum code coverage


I have following trigger that validate some field's value before Opportunity Won and specific profile can revoke this trigger validation.
It works fine as expected but struggling to get 100% test code coverage on the .addError method

Can someone help me here?



trigger validSchedule on Opportunity (before update) {
    List<Id> oppsIDs = new List<Id>();  
        Id distributionId = '00e200000';
        for(Opportunity opp : Trigger.new) {
            if(opp.StageName == 'Confirmation') {
            List<OpportunityLineItem> oli = [Select Id, Schedule_start_date__c, Contract_start_date__c, HasRevenueSchedule from OpportunityLineItem where Opportunity.Id in :oppsIds];           
            if(oli.size() > 0) {               
                for (OpportunityLineItem olis : oli) {  
                    if(olis.Schedule_start_date__c < olis.Contract_start_date__c && olis.HasRevenueSchedule == true
                      && UserInfo.getProfileId() != distributionId) {
                        Trigger.new[0].addError('My ERROR Message');  /* Does not get the code coverage */

Test Class:

private class validScheduleTest{

    static testMethod void myUnitForvalidScheduleTest() {
      Pricebook2 pb = [Select Id, Name From Pricebook2 Where IsStandard = true Limit 1];
       Account act = [SELECT Id from Account LIMIT 1];      
        // Create a test Opportunity for the Subscription contract
        Opportunity o  = new Opportunity();
        o.Name         = 'TEST valid Contract';
        o.AccountId    = act.Id;
        o.CloseDate    = Date.today();
        o.StageName    = 'Interest';      
        insert o;

        // Create a test product2
        Product2 p = new Product2();
        p.Name     = 'TEST valid Sub';
        p.CanUseRevenueSchedule = true;
        p.NumberOfRevenueInstallments = 2;

        insert p;
        // Create a test pricebook entry.
        PricebookEntry pbe = new PricebookEntry();
        pbe.Pricebook2Id = pb.id;
        pbe.Product2Id   = p.id;       
        pbe.IsActive     = true;
        pbe.UnitPrice    = 500.00;
        insert pbe;
        // Create a test Opportunity line item
        OpportunityLineItem i = new OpportunityLineItem();
        i.opportunityId       = o.id;
        i.pricebookentryid    = pbe.id;
        i.quantity            = 1;
        i.TotalPrice = 1000.00;
        i.ServiceDate = Date.today();
        insert i;
        OpportunityLineItemSchedule[] OliSchInsert = new OpportunityLineItemSchedule[]{};
            Date curDate = Date.today().addDays(-2);
            for(Integer x=0; x < 3; x++) {
             OpportunityLineItemSchedule OliSchIn = new OpportunityLineItemSchedule();
                OliSchIn.OpportunityLineItemId = i.Id;
                OliSchIn.Revenue = 500.00;
                OliSchIn.Type = 'Revenue';
                OliSchIn.ScheduleDate = curDate;
                curDate = Date.today().addMonths(2);               
         insert OliSchInsert;      
        o.StageName = 'Confirmation';
            update o;
         catch(Exception ex){
             Boolean expectedExceptionThrown =  ex.getMessage().contains('My Error Message') ? true : false;
                System.AssertEquals(expectedExceptionThrown, true);
Hi Domdick,

I faced this issue earlier and the way I resolved it by following the below approach :-

a. Write code in the test class that will cause the trigger to 'addError()'.
b. Surround the above test class code with try - catch.
c. Assert that an exception is thrown and that the exception message is the same one you created with 'addError()'.

ere's an example (partly pseudo) code from both trigger and test class:


if(myRecord.MyField == some value)
myRecord.addError('My Error Message');

Test Class:

MyRecord.MyField = a value that will cause an error;
update MyRocord;
throw new MyException('An exception should have been thrown by the trigger but was not.'); // 1. If we get to this line it means an error was not added and the test class should throw an exception here. 2. MyException class extends Exception.
catch(Exception e)
Boolean expectedExceptionThrown =  e.getMessage().contains('My Error Message')) ? true : false;
System.AssertEquals(expectedExceptionThrown, true);

Hope this helps !!
Fake it by reproducing data that pass the if -case and let your code delve in to addError , once in print it using System.Debug, the error message should be in your logs. Coming to standard practice, I think if your code is 99 percent that you own quality code, this is exception and can be faked or else can be left unless your right piece of code is working