You need to sign in to do that
Don't have an account?
wcwill978
Need Help Increasing Test Coverage
Hi I have a trigger that creates a custom object when an opportunity stage is set to "closed lost" and saved. I created a test class to deploy into prod, but can only get 64%coverage. Can someone help me increase my test coverage or guide me in the right dirrection so I can get as close to 100% Also when I run the test I get one Test Failure: System.DmlException: Insert failed. First exception on row 0; first error: REQUIRED_FIELD_MISSING, Required fields are missing: [CloseDate]: [CloseDate]
Below is my test Class:
@isTest
private class MyTestWLATrigger
{
static testmethod void TestMethod1()
{
//Fill all mandatory properties of opportunity and don't miss stage name
Opportunity opp = new Opportunity() ;
opp.Name = 'Test Oppty' ;
opp.stageName = '4: Generate Offer' ;
opp.WonLostReason1__c = '' ;
//Now insert the opportunity
insert opp ;
//To let your trigger code covered in write this
opp.stageName = 'Closed Lost' ;
//change the stage name
opp.WonLostReason1__c = 'Price' ;
//Now update the opportunity
update opp ;
System.assertEquals(opp.Name, opp.stageName, opp.WonLostReason1__c);
}
}
And below is my trigger:
trigger AutoCreateWinLossAnalysisOnOpportunity on Opportunity (after update)
{
List<Opportunity> closedOps = new List<Opportunity>();
List<Win_Loss_Analysis__c> newwinLossObjects = new List<Win_Loss_Analysis__c>();
List<Win_Loss_Analysis__c> updatewinLossObjects = new List<Win_Loss_Analysis__c>();
List<RecordType> recordTypesForOppty = new List<RecordType>();
recordTypesForOppty = [Select Name, ID From RecordType where SobjectType = 'Win_Loss_Analysis__c'];
System.debug('recordTypesForOppty'+recordTypesForOppty);
List<Id> ExistingIds = new List<Id>();
Integer count = Trigger.new.size();
for(Opportunity newvalue : Trigger.new)
{
Opportunity oldvalue = Trigger.oldMap.get(newvalue.Id);
if(oldvalue.StageName != newvalue.StageName || oldvalue.WonLostReason1__c != newvalue.WonLostReason1__c)
{
if(newvalue.StageName == 'Closed Lost'){
if(newvalue.WonLostReason1__c == 'Price'
|| newvalue.WonLostReason1__c == 'Product Feature/Functionality'
|| newvalue.WonLostReason1__c =='Relationship')
{
System.debug('newvalue'+newvalue);
closedOps.add(newvalue);
ExistingIds.add(newvalue.Id);
}
}
}
}
system.debug('Found : ' + closedOps.size() + ' Opps that need analysis records created');
if (closedOps.size() > 0)
{
List<Win_Loss_Analysis__c> existing = [SELECT Id,Opportunity_Name__c FROM Win_Loss_Analysis__c WHERE Opportunity_Name__c in :ExistingIds];
system.debug('Found : ' + existing.size() + ' Existing Win Loss Records');
string LossAnalysis = null;
for (Opportunity oppty : closedOps)
{
// get the recordTypeId
Id WinLossObjectRecordTypeId = null;
string typeName;
LossAnalysis = oppty.WonLostReason1__c.toLowerCase();
System.debug('******LossAnalysis *******'+LossAnalysis);
for (RecordType recordType : recordTypesForOppty)
{
System.debug('recordType'+recordType);
typeName = recordType.Name.toLowerCase();
System.debug('recordType.Name.toLowerCase()>>>>>>>'+recordType.Name.toLowerCase());
System.debug('******typeName *******'+typeName );
if (LossAnalysis == 'price' && typeName == 'price (lost)')
{
System.debug('ist if>>>>>>');
WinLossObjectRecordTypeId = recordType.Id;
}
if (LossAnalysis == 'product feature/functionality' && typeName == 'productfeature (lost)')
{
System.debug('2nd if>>>>>>');
WinLossObjectRecordTypeId = recordType.Id;
}
if (LossAnalysis == 'relationship' && typeName == 'relationship (lost)')
{
System.debug('3rd if>>>>>>');
WinLossObjectRecordTypeId = recordType.Id;
}
}
system.debug('Record type id: ' + WinLossObjectRecordTypeId + ' found for oppt id' + WinLossObjectRecordTypeId );
// construct the new custom object with the required fields set
Win_Loss_Analysis__c wL = new Win_Loss_Analysis__c();
System.debug('oppty.Id>>>>>>>'+oppty.Id);
wL.Opportunity_Name__c = oppty.Id;
wL.RecordTypeId = WinLossObjectRecordTypeId;
System.debug('*************Checking RecordTypeId***********'+WinLossObjectRecordTypeId);
System.debug('WinLossObjectRecordTypeId>>>>>>>'+WinLossObjectRecordTypeId);
wL.Account_Name__c = oppty.AccountId;
System.debug('oppty.AccountId>>>>>>>'+oppty.AccountId);
if(existing.size() > 0)
{
for(Win_Loss_Analysis__c exist : existing)
{
if(exist.Opportunity_Name__c == oppty.Id)
{
wL.Id = exist.Id;
break;
}
}
}
if(wL.Id == null)
{
newwinLossObjects.add(wL);
}
else
{
updatewinLossObjects.add(wL);
}
}
}
system.debug('Inserting ' + newwinLossObjects.size() + ' new Win Loss Objects' );
system.debug('Updating ' + updatewinLossObjects.size() + ' Win Loss Objects' );
if(newwinLossObjects.size() > 0)
insert newwinLossObjects;
if(updatewinLossObjects.size() > 0)
update updatewinLossObjects;
}
Assertion Failed means that your trigger or Apex Classes executed all the way through, but there was a logic error (according to your test method). Consider this obvious example:
In this code, I'm expecting myInt to be the value 1, but because of a typo, myInt will actually be 2. This will cause the System.Exception as you posted (except something like "Expected: 1, Actual: 2"). Doublecheck your logic to make sure that the test actually models what you're trying to do, and then doublecheck your functions to make sure they're actually written the way they're supposed to be. This check and balance system is exactly why code coverage is forced upon us hapless developers. It makes us consider our code carefully to ensure that we're getting the results we expect.
All Answers
In your test method, add opp.closedate = date.today(); after the 8th line.
Thank you DCBoy,
I added this line, and it decreased my overall test coverage down to 44%. On my trigger though it covered it at 84%.
Average test coverage across all Apex Classes and Triggers is 44% and now received this new error:
System.DmlException: Update failed. First exception on row 0 with id 006T0000007ZCMYIA4; first error: CANNOT_INSERT_UPDATE_ACTIVATE_ENTITY, AutoCreateWinLossAnalysisOnOpportunity: execution of AfterUpdate caused by: System.DmlException: Insert failed. First exception on row 0; first error: REQUIRED_FIELD_MISSING, Required fields are missing: [Account_Name__c]: [Account_Name__c] Trigger.AutoCreateWinLossAnalysisOnOpportunity: line 109, column 10: []
To make sure you are setting all the required fields in your test method, create a new opportunity from the UI and note down all the fields that are mandatory. All of those need to be set in your test method as well.
Hi DCBoy,
All the required fields for when the oppty is closed are already set in the test method. That error message for the required field [Account_Name__c] is a custom field in the custom object that the trigger is creating. This Account name is automatically pulled from the oppty and auto filled by the trigger. Here is the updated trigger: When I run this now the overall test coverage decreased.
You need to associated the account created in the first line (Account a) to the opportunity record being inserted (opp.accountid = a.id;)
That got rid of the errors, but my code coverage is still at 21% I dont get it. Before it was at 64% and now its this low. Also this new message poped up:
System.Exception: Assertion Failed: Expected: Closed Lost, Actual: Price
Assertion Failed means that your trigger or Apex Classes executed all the way through, but there was a logic error (according to your test method). Consider this obvious example:
In this code, I'm expecting myInt to be the value 1, but because of a typo, myInt will actually be 2. This will cause the System.Exception as you posted (except something like "Expected: 1, Actual: 2"). Doublecheck your logic to make sure that the test actually models what you're trying to do, and then doublecheck your functions to make sure they're actually written the way they're supposed to be. This check and balance system is exactly why code coverage is forced upon us hapless developers. It makes us consider our code carefully to ensure that we're getting the results we expect.