+ Start a Discussion
Kalle KalifKalle Kalif 

Problem getting test coverage on inbound email service

Good day esteemed experts,


I am unable to increase the test coverage of my email-recieving class above ~50%.


Email Class:


global class DailyRecieve implements Messaging.InboundEmailHandler
global Messaging.InboundEmailResult handleInboundEmail(Messaging.inboundEmail email,Messaging.InboundEnvelope envelope){
Messaging.InboundEmailResult result = new Messaging.InboundEmailResult();


//prepare dummy list for use if data source does not contain certain fields
string[] dummy=new List<String> ();

//Retrieve Truck name from License number
string[] Licenseno = source.split('<License>',3);
string License= Licenseno[1].trim().substring(0);
Truck__c[] Truck = [select Name from Truck__c where License_no__c = :License Limit 1];

//Retrieve data
string[] OBJECT_ID=((source.contains('<OBJECT_ID>') == false)? dummy :source.split('<OBJECT_ID>',3));
string[] OPERATION_CODE=((source.contains('<OPERATION_CODE>') == false)? dummy :source.split('<OPERATION_CODE>',3));
string[] REPORT_VERSION=((source.contains('<REPORT_VERSION>') == false)? dummy :source.split('<REPORT_VERSION>',3));
string[] REPORT_NOON=((source.contains('<REPORT_NOON>') == false)? dummy :source.split('<REPORT_NOON>',3));
string[] REPORT_OFFHIRE=((source.contains('<REPORT_OFFHIRE>') == false)? dummy :source.split('<REPORT_OFFHIRE>',3));
string[] REPORT_DATE=((source.contains('<REPORT_DATE>') == false)? dummy :source.split('<REPORT_DATE>',3));

String RptName = (Truck[0].Name+' '+REPORT_DATE[1].substring(0,16));

//Input db

Daily__c r = new Daily__c(Name = RptName, Truck_Name__c = Truck[0].ID, Email_from__c = email.fromAddress,
Object_ID__c=(integer.valueof(OBJECT_ID[1].trim().length()) == 0)? null :decimal.valueof(OBJECT_ID[1].trim()),
Operation_code__c=(integer.valueof(OPERATION_CODE[1].trim().length()) == 0)? null :decimal.valueof(OPERATION_CODE[1].trim()),
Report_Version__c=(integer.valueof(REPORT_VERSION[1].trim().length()) == 0)? Null :REPORT_VERSION[1],
Report_Noon__c=(integer.valueof(REPORT_NOON[1].trim().length()) == 0)? null :decimal.valueof(REPORT_NOON[1].trim()),
Report_Offhire__c=(integer.valueof(REPORT_OFFHIRE[1].trim().length()) == 0)? null :decimal.valueof(REPORT_OFFHIRE[1].trim()),
Report_Date__c=(REPORT_DATE[1] == '0' || integer.valueof(REPORT_DATE[1].trim().length()) == 0)? Null : datetime.valueof(REPORT_DATE[1])


upsert r Name; 
return result;


Test method:

private class DailyRecieve_Test 
static testMethod void test234567() {

  // create a new email and envelope object
  Messaging.InboundEmail email = new Messaging.InboundEmail() ;
  Messaging.InboundEnvelope env = new Messaging.InboundEnvelope();
  // setup the data for the email
  email.subject = 'dailyreptest';
  email.fromname = 'FirstName LastName';
  env.fromAddress = 'someaddress123@someverifieddomain.com';
  email.plainTextBody= '<OBJECT_ID>334<OBJECT_ID>'
+'<REPORT_DATE>2012-01-04 18:00:00<REPORT_DATE>';
  // call the email service class and test it with the data in the testMethod
  DailyRecieve dailytest = new DailyRecieve();
  dailytest.handleInboundEmail(email, env);
  // query for the daily_report the email service created
  Daily__c daily = [select id, OBJECT_ID__c,  REPORT_NOON__c, REPORT_OFFHIRE__c, from Daily__c where OBJECT_ID__c = 334];
  System.assertEquals(daily.REPORT_NOON ,1);


The thing is gives me 50% coverage. When looking at test coverage "line-for-line", all lines related to allocation of data to custom fields are colored red, meaning they are not properly tested. 


Any ideas?

Kalle KalifKalle Kalif



Are you saying the Retrieve Data section or the Input Db section are not being tested?

Kalle KalifKalle Kalif

The Input Db section is not being tested - thats about 50% of the code.


Weird.  Does it seem like that section is getting skipped?  If you insert system.debug() before and after that section, are they executed?


What happens if you comment out that section and replace with a very basic line like


Daily_c r = new Daily__c(Name = 'Test');


Kalle KalifKalle Kalif

It doesnt look like it is skipped. If I replace it with a basic input line like you suggested everything works fine.


I think that it might be the IF/ELSE statements inside the new record section that is not being tested. How do i properly test these?


Object_ID__c=(integer.valueof(OBJECT_ID[1].trim().length()) == 0)? null :decimal.valueof(OBJECT_ID[1].trim()),



You could write a class to convert the zeros to null and call that in place of the conditional statements.

Kalle KalifKalle Kalif

That might be a solution, but i cannot see how to solve the problem with regards to date/time fields: There are actually 5-6 datetime fields in my custom Object, and the inbound email might populate a new record with only a few of them, leaving the others blank.


So if i have date1__c, date2__c, date3__c, and want to be able to populate them only if they are present in the email, I cannot see another solution than what I already have??


date1__c=(date1[1] == '0' || integer.valueof(date1[1].trim().length()) == 0)? Null : datetime.valueof(date1[1])
date2__c=(date2[1] == '0' || integer.valueof(date2[1].trim().length()) == 0)? Null : datetime.valueof(date2[1])