I am writing a test for a 'before insert' trigger. In the trigger, an exception is thrown if there is a problem with the validation (by design). In production, the trigger catches the exception and sends an email, but during testing, the exception is rethrown so it can be caught by the test. I did it in this way for a few reasons:
- Data could be propagated to the test
- It is not desirable to send email when testing
- A custom exception is easier to test for
The trigger code is similar to:
trigger ValidationTrigger on ValidationObject (before insert)
{
try { ValidationTriggerHandler.throwOnErrors(trigger.new); }
catch (ValidationException xception)
{
EmailUtil emails = new EmailUtil()
//prepare email message(s) with 'emails' object here
if (EmailUtil.DoSend) { emails.send(); }
else
{
if (Test.isRunningTest())
{
//custom exception re-thrown so test class can process it
throw xception;
}
}
}
}
And the test class is similar to this:
static testMethod void DuplicateContact()
{
EmailUtil.DoSend = false;
//insert test data to cause the validation to fail
try
{
ValidationObject object = new ValidationObject();
//populate object
//this insert will cause the trigger to execute
insert object;
system.assert(false, 'An expected exception was not thrown');
}
catch (ValidationException xception)
{
//never executed
}
catch (DmlException xception)
{
system.debug('CAUGHT DML EXCEPTION ' + xception.getMessage());
{
Exception innerException = xception.getCause();
if (innerException != null)
{
//this line is not printed in the debug log
system.debug('InnerException message: ' + innerException.getMessage());
}
else
{
//this line is printed in the debug log
system.debug('no inner Exception');
}
}
}
}
The problem I have is this: The custom exception that is re-thrown in the trigger causes a DML exception because the insert was unsuccessful. This in turn means the custom exception has been handled and can't be caught by the test. I called the 'getCause' method of the DMLException which is supposed to return 'the cause of the exception as an exception object', but it is null.
What is really frustrating about this is that the debug log actually says 'caused by: ValidationException: Script-thrown exception' (this is not printed from my code). So Salesforce actually states it knows the exception that caused the problem, but it isn't giving me access to it via the 'getCause' method of the exception that Salesforce throws.
So, how can I get access to the custom exception in the test? Is there a better way to test that a trigger handles errors properly?
if (Test.isRunningTest())
clause? Use a custom setting or a utility class for the purpose to handle it.