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
Chris - ARIChris - ARI 

Apex Class and Trigger

I recently inherited a Salesforce org with almost no code coverage. I am trying to write some test classes for the triggers already in production. The test keeps failing with the below error and I think it is related to the trigger. Can someone shed some light on the below error? My developer skils are very basic.

Test Class:
@isTest
public class Test_OppWonChatter {
    static testMethod void insertNewOpportunity(){

        Opportunity o = new Opportunity();
        o.name = 'Test';
        o.AccountId = '0015500000GE3OS';
        o.StageName = 'Closed Won';
        o.CloseDate = date.today();
        o.Type = 'New Customers';
        
        insert o;
    }
}



Error:
Time Started8/22/2016 2:57 PM
ClassTest_OppWonChatter
Method NameinsertNewOpportunity
Pass/FailFail
Error MessageSystem.DmlException: Insert failed. First exception on row 0; first error: CANNOT_INSERT_UPDATE_ACTIVATE_ENTITY, OppWonChatter: execution of AfterInsert

caused by: System.DmlException: Insert failed. First exception on row 0; first error: INVALID_CROSS_REFERENCE_KEY, invalid cross reference id: []

Trigger.OppWonChatter: line 31, column 1: []
Stack TraceClass.Test_OppWonChatter.insertNewOpportunity: line 12, column 1

Trigger:
trigger OppWonChatter on Opportunity (after insert, after update) {

String status;
String OppAccName;
String OppOwnerName;
String OppName;   
FeedItem post = new FeedItem();
    
    for(Opportunity o : Trigger.new) {
        if(o.OwnerId == '00560000001NLvS') { //It will not post record for for this user to group. Accountsys
            return;
        }
        else { 
            if(Trigger.isInsert ) { 
                if( o.IsWon == true ) { //This will be executed on new record insertion 
                    for (Opportunity oppty : [SELECT Account.Name, Owner.Name, Name FROM Opportunity WHERE Id =:o.Id] ) {
                        OppAccName = oppty.Account.Name;
                     OppName = oppty.Name;
                    
                        
                        OppOwnerName = oppty.Owner.Name;
                    }   
                    
                    status = OppOwnerName + ' just won ' + OppName + '!';

                                                             
                    post.ParentId = '0F960000000Xbrr';
                    post.Title = o.Name;   
                    post.Body = status;
                    
                    insert post;
                }
            }    
            else {
                if ( Trigger.isUpdate ) {
                    if( o.IsWon == true ) { //This will be executed on update to existing record
                        for (Opportunity oppty : [SELECT Account.Name, Owner.Name, Name FROM Opportunity WHERE Id =:o.Id] ) {
                            OppName = oppty.Name;
                            OppAccName = oppty.Account.Name;  
                            OppOwnerName = oppty.Owner.Name; 
                        }        
                        status = OppOwnerName + ' just won ' + OppName + '!';
                                            
                        post.ParentId = '0F960000000Xbrr';
                        post.Title = o.Name;
                        post.Body = status;
                        
                        insert post;      
                    }
                }
            }
        }
    }    
}

 
JeffreyStevensJeffreyStevens
The test coverage is trying to specify the AccountID. Hard-coding IDs is never a good idea.

Change the test class to insert a new account, then use that newly inserted ID and specify it in the building of the opportunity record. 
Chris - ARIChris - ARI
Here is the new test class:
 
@isTest
public class Test_OppWonChatter {
    static testMethod void insertNewOpportunity(){

        Account a = new Account();
        a.name = 'Test';
        a.fleet_size__c = 100;

        Opportunity o = new Opportunity();
        o.name = 'Test';
        o.AccountId = a.Id;
        o.StageName = 'Closed Won';
        o.CloseDate = date.today();
        o.Type = 'New Customers';
        
        insert o;
    }
}

Here is the new error:

Error MessageSystem.DmlException: Insert failed. First exception on row 0; first error: CANNOT_INSERT_UPDATE_ACTIVATE_ENTITY, OppWonChatter: execution of AfterInsert

caused by: System.DmlException: Insert failed. First exception on row 0; first error: INVALID_CROSS_REFERENCE_KEY, invalid cross reference id: []

Trigger.OppWonChatter: line 31, column 1: []
Stack TraceClass.Test_OppWonChatter.insertNewOpportunity: line 16, column 1
JeffreyStevensJeffreyStevens
Do an insert on the account - after line#7.  The ID doesnt get created until an insert is done. 
Chris - ARIChris - ARI
Silly mistake there, but still getting an error for some reason.
 
@isTest
public class Test_OppWonChatter {
    static testMethod void insertNewOpportunity(){

        Account a = new Account();
        a.name = 'Test';
        a.fleet_size__c = 100;
        a.industry = 'Retail';
        
        insert a;

        Opportunity o = new Opportunity();
        o.name = 'Test';
        o.AccountId = a.Id;
        o.StageName = 'Closed Won';
        o.CloseDate = date.today();
        o.Type = 'New Customers';
        
        insert o;
    }
}

Error:
System.DmlException: Insert failed. First exception on row 0; first error: CANNOT_INSERT_UPDATE_ACTIVATE_ENTITY, OppWonChatter: execution of AfterInsert

caused by: System.DmlException: Insert failed. First exception on row 0; first error: INVALID_CROSS_REFERENCE_KEY, invalid cross reference id: []

Trigger.OppWonChatter: line 31, column 1: []
Stack TraceClass.Test_OppWonChatter.insertNewOpportunity: line 19, column 1
Gunnam RamGunnam Ram
Hi Chris,

I guess the issue is with the line 27 in Trigger
post.ParentId = '0F960000000Xbrr';

try to get the Group ID dynamically by querying CollaborationGroup object with GroupName and assign parent ID.
ID CollaborationGroupID = [select ID from CollaborationGroup where name='your groupname'];
post.parentID = CollaborationGroupID;

Please let me know if it resolves your issue.
 
JeffreyStevensJeffreyStevens
Also - unless you have a full sandbox, the IDs of records will change from sandbox to production.  So that means that if you have production IDs hard coded in the trigger, then it won't run correctly in the sandbox or visa versa. So, like Ram said - you need to do a SOQL (Before the For loop - never do a SOQL in a loop) to get the OwnerID (from the User object), and the Parent ID (Not sure what that Id is point to - it's NOT pointing to Account, I can tell that).
Chris - ARIChris - ARI
Ok, here is the new trigger, test class and error:

Trigger:
 
trigger OppWonChatter on Opportunity (after update) {

String OppAccName;
String OppOwnerName;
String OppName;   

 List<FeedItem> posts = new List<FeedItem>();
    
    List<Opportunity> updatedOpps = [SELECT Name, Account.Name, Owner.Name, Amount FROM Opportunity WHERE Id IN :Trigger.newMap.keySet() AND IsWon = true];
    CollaborationGroup chatterGroup = [SELECT Id FROM CollaborationGroup WHERE Name = 'Sales Strategies & Best Practices' LIMIT 1];
    
    for (Opportunity opp : updatedOpps) {
        String status = opp.Owner.Name + ' just won ' + opp.Account.Name + ' for ' + opp.Amount + '!';
        FeedItem post = new FeedItem(
            ParentId = chatterGroup.Id,
            Title = opp.Name,
            Body = status
        );
        posts.add(post);
    }
    insert posts;
}


Test Class:
 
@isTest
public class Test_OppWonChatter {
    static testMethod void insertNewOpportunity(){

        Account a = new Account();
        a.name = 'Test';
        a.fleet_size__c = 100;
        a.industry = 'Retail';
        
        insert a;

        Opportunity o = new Opportunity();
        o.name = 'Test';
        o.AccountId = a.Id;
        o.StageName = 'Closed Won';
        o.CloseDate = date.today();
        o.Type = 'New Customers';
        
        insert o;
        
        o.name = 'Testing 123';
        update o;
        
    }
}


Error:

Error MessageSystem.DmlException: Update failed. First exception on row 0 with id 00655000007Yt5dAAC; first error: CANNOT_INSERT_UPDATE_ACTIVATE_ENTITY, OppWonChatter: execution of AfterUpdate

caused by: System.QueryException: List has no rows for assignment to SObject

Trigger.OppWonChatter: line 10, column 1: []
JeffreyStevensJeffreyStevens
So, line #10...
CollaborationGroup chatterGroup = [SELECT Id FROM CollaborationGroup WHERE Name = 'Sales Strategies & Best Practices' LIMIT 1];

There must not be a CollborationGroup record with the name of 'Sales Strategies & Best Practices'. Anytime you do a SOQL and don't put it in a list - then you must have exactly one record returned.  If you have zero, or more than 1 - you'll get an error. 
Chris - ARIChris - ARI
There is. I made sure and created it myself.
User-added image
JeffreyStevensJeffreyStevens
I've never used that object before - but I'd do a SOQL on it from Workbench, Eclipse, or Developer console - just to prove to me the name of the record.
Chris - ARIChris - ARI
The newly written Trigger actually works too and it post to the chatter group. I'm at a loss here.
Gunnam RamGunnam Ram
Then your issue is with Test class only?
Chris - ARIChris - ARI
Yes, the old trigger worked too. I am just trying to get code coverage. Until then I can't import any new triggers to production.
Suraj Tripathi 47Suraj Tripathi 47
Hi Chris,
Greetings!

Please trace in the debug log.
There should be some permission issue with the current user regarding the specific record type.
So please check again the user and permission. 

If you find your Solution then mark this as the best answer. 

Thank you!

Regards,
Suraj Tripathi