5

I've a Apex class as below and i've to write test class for that.

trigger SetAccountStatus on job__c (after insert) {
    List<Account> AccSt = new List<Account_Status__c>();
    List<Account> updatedAccSt = new List<Account_Status__c>();
    List<Id> patientIds = new List<Id>();
    for (job__c  job: trigger.new) {
        patientIds.add(patient.id);
    }

    AccSt = [SELECT Id, Account_Status__c FROM Account WHERE job__c IN :patientIds];

    for(Account_Status__c a :AccSt) {
        a.Account_Status__c = true;
        updatedAccSt.add(a);
    }

    if(updatedAccSt.size() > 0) {
        try{
            update updatedAccSt;
        } catch(DMLException e){
        // here is code to send Email and other operation

        }
    }
}

If this class may has mistake please consider, because this is not a actual class this is just example to explain my senario. My class is too big.

I'm writing test class and i've to cover the catch block in test class. but to cover the catch we need to pass such data which we cause run time exception i.e. DML exception but this is not possible in my case; to occur run time exception.

So to cover try block i'm thinking throw the exception manually so that it will cover the catch block.

public class myexceptionextends Exception {}

// method start
try{
    update updatedAccSt;
    if(Test.isRunningTest()){
        throw new myexception('Error');   
        // it goes to catch block
    }
}

SO here problem is exception must be DML exception it gives error Non-virtual and non-abstract type cannot be extended:

1
  • actual is i've to first insert the test record as test data so this record must be properly inserted. now after some operation, i've to update the same record in apex class so how this is possible?
    – user29314
    Jul 11, 2016 at 6:45

5 Answers 5

2

There could be other ways to raise a DML Exception. For Example consider testAccount is a Account object in your test data. Now Below code will raise DML exception:

testAccount.Name='===================================================================================================Some string which is longer than 255 characters================================================================================================================';
update testAccount;

A DML Exception will be thrown and catch block would be covered. So you need to modify your test data accordingly.

Here is some sample code:

try{
    if(Test.isRunningTest() && updatedAccSt.size() > 0 && 
        updatedAccSt[0].Name='Exception Account'){
        updatedAccSt[0].Name='===================================================================================================Some string which is longer than 255 characters================================================================================================================';
    }
    update updatedAccSt;
}
4
  • Hi Mukesh, its not a case. actually first i've to insert proper test data record and after some operation again update the same record in apex class in try block. so how?
    – user29314
    Jul 11, 2016 at 6:35
  • @Amol: Look at revised answer. Jul 11, 2016 at 6:44
  • Hi Mukesh, I think it solve my problem, but in another case i dont have such name field and any other required field. in this case i've only currency, picklist and date field.
    – user29314
    Jul 11, 2016 at 7:04
  • Name is standard field that exist on all objects. You can also try assigning string to currency field. It will result DML exception. Jul 11, 2016 at 8:24
3

Its easy.

throw new DMLException('My DML EXCEPTION'); 
3

The easiest way to intentionally throw DML exception is insert record without setting required field.

Quote:

Any problem with a DML statement, such as an insert statement missing a required field on a record.

To bring more clarity here is code spinet for your reference:

try{
    Account a = [Select id, name from account limit 1];
    a.name = '';
    update a;    
}
Catch(Exception e){
    system.debug('Exception ' + e);
}
2
  • It is not possible in my case, because i am insert the record as test data so this record must be properly inserted. now after some operation, i've to update the same record. so how this is possible? In another case i dont have required field
    – user29314
    Jul 11, 2016 at 6:26
  • @Amol your name field is always read only field so update this field in your test class, it will throw an error.
    – MIX DML
    Jul 11, 2016 at 7:54
1

I too tried to throw my own DmlException because reasons and while this is certainly doable it will fail horribly if you depend on its specific properties. In my case, I have no option to manually trigger the exception with the correct errors but if I just throw the error, a simple call of getDmlMessage() will fail and actually cause the dreaded UnexpectedException.

So, here are your options:

  1. Raise it manually and live with the consequences (aka "uncatchable errors").
  2. Raise a custom exception and handle it separately. You might need to catch multiple exceptions at once which is not implemented in Salesforce right now, so you need a workaround for that.
  3. If you just need to trigger a non-specific DmlException go with Mukesh's answer. Note that this will not work if you have to test for specific errors.

Imho the exception system in Salesforce could really need a rework to prevent all these hassles. Hope this helps someone for the time being.

0

Just try to insert a new contact without any field as below. This will throw a DML exception as lastname is required for creating a new Contact.

insert new Contact();

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .