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
SF NinjaSF Ninja 

Test Method Error

Hello,

 

Hopefully this is a quick question for you geniuses. I'm wrtting a test method(first one) and have an interesting error I cant reconcile.

 

Error:

 

System.DmlException: Update failed. First exception on row 0 with id 006S0000005AsJJIA0; first error: CANNOT_INSERT_UPDATE_ACTIVATE_ENTITY, NewDeploymentCaseFromOpp: execution of AfterUpdate caused by: System.ListException: List index out of bounds: 0 Trigger.NewDeploymentCaseFromOpp: line 8, column 1: []

 

My test Code

 

}

 

@isTest
public class Test {
    static testMethod void myTest() {
        Account account = new Account (name='some name account');
        insert account; 
        Contact contact = new Contact (lastname='some', Account=account, email='rawr@rawr.com'); 
        insert contact; 
        DateTime dT = System.now();
        Date myDate = date.newinstance(dT.year(), dT.month(), dT.day());
        Opportunity NewOpportunity = new Opportunity (name='some name',CloseDate=myDate, booking_type__c='New', stagename='Introductions', Account=account);
        insert NewOpportunity;
        
        NewOpportunity.stagename='Closed Won';
        //test.startTest();
        update NewOpportunity;
        //test.stopTest();
        Case newCase= [SELECT Id, Opportunity__c, Status, Origin, Products__c, RecordTypeId FROM Case WHERE Account.Name = 'some name account'];
        System.assertEquals(newCase.Opportunity__c, NewOpportunity.id);
        System.assertEquals(newCase.AccountId, NewOpportunity.AccountId);
        System.assertEquals(newCase.Status, 'New'); 
        System.assertEquals(newCase.Origin, 'Email');
        System.assertEquals(newCase.Products__c, NewOpportunity.Products__c);
        System.assertEquals(newCase.RecordTypeId, '012S00000004UAS');
        }
        

SF NinjaSF Ninja

Additional Question: When I run my test code, despite the error when i scroll down in Salesforce i see that my Trigger has 100% coverage from my test. However when I look at the trigger itself, it says its only 0%.

 

There appears to be some disconnect? 

craigmhcraigmh

Can you post the relevant code from the NewDeploymentCaseFromOpp trigger? That's where the exception is occurring.

 

The Apex Classes/Apex Triggers listing pages don't seem to update the test coverage immediately (don't ask me why). But if you do open up one of the classes, the updated coverage will be accurate at the top of the page.

SF NinjaSF Ninja

Here is the relevant code. Any help would be very appreciated. I should note that whenever I run the test, I'm getting an error on the line where I have "update NewOpportunity;" which I can not make heads or tails of. 

 

}

        

trigger NewDeploymentCaseFromOpp on Opportunity (after update

 

Id rtId = [select Id,name from RecordType where name='Deployment' and SObjectType='Case' limit 1].Id;

Id qId = [select Id, QueueId, Queue.Name from QueueSobject where SobjectType='Case' AND Queue.Name='Deployment' limit 1].Id;

 for (Opportunity opp : Trigger.new

 { 

    if ( (opp.stagename == 'Closed Won' ) && (opp.booking_type__c != 'Renewal') && (trigger.oldMap.get(opp.id).stagename != 'Closed Won' ) )

         {

         

         

         list<Account> act=[select id,name from Account where Id=:opp.AccountId];

         list<contact> ct=[select id from Contact where AccountId=:act[0].id];

                       Case c = new Case

                           AccountID = opp.AccountId, 

                           Opportunity__c = opp.id,

                           Status = 'New'

                           Origin = 'Email',

                           ContactID = ct[0].id,

                           Products__c = opp.Products__c,

                           Subject = 'Deployment Case for '+act[0].name, 

                           OwnerId= qId, 

                           RecordTypeId = rtId, 

                           Account_Executive__c = opp.OwnerId

                           );   // This is my id for testing purposes

                           

                       insert c; 

                       break;

                    }

           

    

 } 

 

 

 

============

Updated Test Method

============

 

}

@isTest

publicclass Test {

    statictestMethodvoid myTest() {

        Account account = new Account (name='some name account');

        insert account; 

        Contact contact = new Contact (lastname='some', AccountId=account.Id, email='rawr@rawr.com'); 

        insert contact; 

        DateTime dT = System.now();

        Date myDate = date.newinstance(dT.year(), dT.month(), dT.day());

        Opportunity NewOpportunity = new Opportunity (name='some name',CloseDate=myDate, booking_type__c='New', stagename='Introductions', AccountId=account.Id);

        insert NewOpportunity;

        

        NewOpportunity.stagename='Closed Won';

        //test.startTest();

        update NewOpportunity;

        //test.stopTest();      

        Case newCase= [SELECT Id, Opportunity__c, Status, Origin, Products__c, RecordTypeId FROM Case WHERE Account.Name = 'some name account' ];

        System.assertEquals(newCase.Opportunity__c, NewOpportunity.id);

        System.assertEquals(newCase.AccountId, NewOpportunity.AccountId);

        System.assertEquals(newCase.Status, 'New'); 

        System.assertEquals(newCase.Origin, 'Email');

        System.assertEquals(newCase.Products__c, NewOpportunity.Products__c);

        }

        

craigmhcraigmh

Here are the two important lines:

 

list<Account> act=[select id,name from Account where Id=:opp.AccountId];
list<contact> ct=[select id from Contact where AccountId=:act[0].id];

 

You have to make sure that opp.AccountId != null. If it is null, the "act" List will be empty, and the second line will fail.

SF NinjaSF Ninja

Thank you, 

I updated the IF statement that proceeds these lines with a catch. It now reads as:

 if ( (opp.stagename == 'Closed Won' ) && (opp.booking_type__c != 'Renewal') && (trigger.oldMap.get(opp.id).stagename != 'Closed Won' ) && (opp.AccountId!=null) )

 

 

So if an opportunity has an AccountId = null, it should stop there.

 

However I'm still receiving an error from Force.com IDE when I run my test as follows:

 System.DmlException: Update failed. First exceoption on row 0 with id 006S0000005AsHoIAK; first error: CANNOT_INSERT_UPDATE_ACTIVITY_ENTITY, NewDeploymentCaseFromOpp: Execution of AfterUpdatre caused by: System.DmlException: Insert failed. First exception on row 0; first error: FIELD_INTEGRITY_EXCEPTION, Owner ID: id value of incorrect type: 03gS000000Bvf3IAC: [OwnerId] Trigger.NewDeploymentCaseFromOpp: line 27, Column 1:[]

 

 

My guess here is the insert in my test code is somehow failing, and it something with my owner id's is not jiving.. 

craigmhcraigmh

Well, yeah...if you do a describe on the Case SObject, you'll see that the OwnerID has to have an Id from the Group or User SObject...can't take one from QueueSObject.

SF NinjaSF Ninja

Ok i got around that by just using the id for the queue hard coded (wont that be a problem when i deploy to live and the id there is different, albeit static?).

 

Now that i changed my owner, i only have one error, but I again cant figure it out.

 

"System.SObjectException: SObject row was retrieved via SOQL without querying the requested field: Case AccountId"

 

 

It should be worth noting that Delphi is also telling me that for both my 'test' and trigger im at 0 lines not tested, 100% covered. Can I just deploy?

SF NinjaSF Ninja

By the by, thank you for all this attention. Its a big relief to have some help:) 

SF NinjaSF Ninja

I think i figured it out. In my test batch, when I was created 'newCase' i did not have AccountId as part of my select. I inserted it..an no errors.

 

 

I'm hesistant of what i do next, this is my first apex trigger. 

craigmhcraigmh

Yeah, you have to query the field in your test:

 

Case newCase= [SELECT Id, Opportunity__c, ​Status, Origin, Products__c, RecordTypeId, AccountId FROM Cas​e WHERE Account.Name = 'some name account'];
        System.assertEquals(newCase.Opportunity__c​, NewOpportunity.id);
        System.assertEquals(newCase.AccountId, New​Opportunity.AccountId);

 

And you should probably just set the Owner of the case to something that makes sense, like the current user's ID.

 

 

 

I'm glad to help...these boards have definitely given me help, and I'm glad to give back.

 

SF NinjaSF Ninja

Its up and its working!

 

I'm having the cases assigned to a queue for the moment, since that is what makes sense in our workflow.

 

 

Question: in my virgin use of this trigger, everything happened as expected, except no email was sent to the queue users. I had set up the queue so they get emails when new cases are created. Do cases created by triggers not follow those rules? If so, is there some way around it, or to force salesforce to message those team members? 

 

EDIT: Ok my research indicates this should be possible. That is to say, instead of assigning the case, I should be able invoke case assignment rules from my Apex code, I just cant find any documentation on it. 

SF NinjaSF Ninja

So...

 

I found this http://boards.developerforce.com/t5/Apex-Code-Development/using-DMLOptions-in-trigger-not-working/m-p/124795?jump=true#M15172

 

 

So..what i gather, all i need to do is update my trigger with the following lines of code, after my insert but before my break.

 

Does this look silly?

 

                Database.update(theCase);    

Database.DMLOptions dmo = new Database.DMLOptions();
                dmo.emailHeader.triggerUserEmail = true;
                dmo.assignmentRuleHeader.useDefaultRule = true;
                theCase.setOptions(dmo);

craigmhcraigmh

 I wish I could help you more, but you've hit the limit of my knowledge...

 

 

But when it comes to testing, you want to make sure that you have absolutely zero failures. Also, 75% test coverage is required, but 100% is recommended (yes, I know I sound like a textbook).

SF NinjaSF Ninja

One more question, going back to some raw programing.

 

On my sandbox and production i have 2 fields, both called Opportunity (a custom field in case, which is a lookup to opportunity).

 

When i run my code on sandbox, this field is being populated normally from the trigger (per my code).

On production, this ONE field is not being populated, which seems odd.

 

Ideas?