[SalesForce] Unit Test is Providing 0% Coverage for Apex Trigger

New to Apex here. I cobbled together a trigger that creates a new task whenever a certain type of opportunity is Closed – Lost, but I can't figure out how to get ANY coverage with a unit test. Does anyone see what I am doing wrong here?

Trigger:

trigger OpportunityAfter on Opportunity (after update){

Set AccountIDs = new Set();

for(Opportunity o : trigger.new){
     AccountIDs.add(o.AccountId);
}

for(Opportunity opp : trigger.new)
if(opp.StageName == 'Closed - Lost' && trigger.oldMap.get(opp.Id).StageName != opp.StageName)
AccountIds.add(opp.AccountID);

Task[] tasksToInsert = new Task[]{};

for (Account acc : [Select Id, Name, OwnerId from Account where Id IN :AccountIds]) 
for (Opportunity opp : trigger.new)
if(opp.StageName == 'Closed - Lost' && opp.Business_Line__c == 'Workforce' && opp.Survey_Type__c != 'APulse' && trigger.oldMap.get(opp.Id).StageName != opp.StageName)
tasksToInsert.add(new Task(WhatId=acc.Id, OwnerId=opp.OwnerId, Subject='Follow-up: ' + opp.name + ' - ' + acc.name, ActivityDate=(opp.CloseDate + 180), Description='Follow up to see how engagement initiatives are going and if Avatar can help. Refer to lost opportunity: ' + opp.name));

if(tasksToInsert != null && !tasksToInsert.isEmpty())
Database.insert(tasksToInsert);

}

Test:

@isTest
public class TestClass {

    static testMethod void myUnitTest() {

    //Set up user
    User u1 = [SELECT Id FROM User WHERE Email='abc@sampleemail.com'];

    //Run As U1
    System.RunAs(u1){

    System.debug('Testing trigger... (single record validation)');

    //NEW Account record
    Account acc = new account();
    acc.Name = 'Test Account';
    acc.Industry = 'Healthcare';

    insert acc;

    //NEW Opportunity record
    Opportunity opp = new Opportunity();
    opp.Name = 'Test Opportunity'; 
    opp.CloseDate = System.today();
    opp.StageName = 'S1 - Investigative';
    opp.Type = 'Repeat Business - Wrkforce HC';
    opp.AccountId = acc.Id;
    opp.Survey_Type__c = 'Product Name';

    insert opp;

    opp.StageName = 'Closed - Lost';
    opp.Reason_Won_Lost__c = 'Relationship';

    update opp;

    //NEW Task record   
    Task testTask = new task();
    testTask.WhatId = acc.Id;
    testTask.Subject = 'Follow-up: ' + opp.name + ' - ' + acc.name;
    testTask.ActivityDate = (opp.CloseDate + 180); 
    testTask.Description = 'Follow up to see how engagement initiatives are going and if we can help. Refer to lost opportunity: ' + opp.name;

    insert testTask;

    //Validate single insert
    System.assertEquals(acc.Id, testTask.WhatId);

    }
    }
}

Best Answer

The trigger code is having lot of redundancy, So I modified it. before posting the modified code few lines of explanation what I changed. you collected account Ids twice and did the condition check twice where once is more enough. I am also made changes to the test class, where Task data is provided which is not required because the trigger has to create it once the necessary conditions are met. I am expecting this trigger should work for you, if there is any errors feel free to post as a comment.

trigger OpportunityAfter on Opportunity (after update){

    Set AccountIDs = new Set();

    for(Opportunity o : trigger.new){
        if(opp.StageName == 'Closed - Lost' && opp.Business_Line__c == 'Workforce' && 
            opp.Survey_Type__c != 'APulse' && trigger.oldMap.get(opp.Id).StageName != opp.StageName){

                AccountIDs.add(o.AccountId);
         }
    }

    Task[] tasksToInsert = new Task[]{};

    for (Account acc : [Select Id, Name, OwnerId from Account where Id IN :AccountIds]){
        for (Opportunity opp : trigger.new){
            if(opp.AccountId == acc.Id){
                Task tas = new Task();
                tas.WhatId=acc.Id;
                tas.OwnerId=opp.OwnerId;
                tas.Subject='Follow-up: ' + opp.name + ' - ' + acc.name;
                tas.ActivityDate=(opp.CloseDate + 180);
                tas.Description='Follow up to see how engagement initiatives are going and if Avatar can help. Refer to lost opportunity: ' + opp.name;
                tasksToInsert.add(tas);                                                         
            }
        }
    }
    if(tasksToInsert != null && !tasksToInsert.isEmpty())
    Database.insert(tasksToInsert);

}

@isTest
public class TestClass {

    static testMethod void myUnitTest() {

    //Set up user
    User u1 = [SELECT Id FROM User WHERE Email='abc@sampleemail.com'];
    test.startTest();  
    //Run As U1
    System.RunAs(u1){

    System.debug('Testing trigger... (single record validation)');

    //NEW Account record
    Account acc = new account();
    acc.Name = 'Test Account';
    acc.Industry = 'Healthcare';

    insert acc;

    //NEW Opportunity record
    Opportunity opp = new Opportunity();
    opp.Name = 'Test Opportunity'; 
    opp.CloseDate = System.today();
    opp.StageName = 'S1 - Investigative';
    opp.Type = 'Repeat Business - Wrkforce HC';
    opp.AccountId = acc.Id;
    opp.Survey_Type__c = 'Product Name';

    insert opp;

    opp.StageName = 'Closed - Lost';
    opp.Reason_Won_Lost__c = 'Relationship';
    opp.Business_Line__c = 'Workforce'  //added this line to meet the if condition while collecting the set of id in the trigger.

    update opp;
   test.stopTest();
    // Here I am expecting the task has been inserted and doing a query for it         and check it in the assert statement.
   Task  testTask=[Select Id, WhatId from Task where WhatId=:acc.Id];
    //Validate single insert
    System.assertEquals(acc.Id, testTask.WhatId);

    }
    }
}
Related Topic