You need to sign in to do that
Don't have an account?
Tolby Hunt
Unit test SMS to new lead
Hello! I am trying to write a unit test for my SMS to new lead trigger and controller. I have no idea on how to unit test for salesforce. please help!
My trigger is -
My class is -
My trigger is -
trigger SMS_To_New on Lead (after insert) { Send_SMS_ControllerLead.Send(Trigger.newMap.keySet()); }
My class is -
public class Send_SMS_ControllerLead { public String smsBody {get; set;} public boolean hasNumber {get; set;} public final String fromNumber = '+1XXXXXXXXXX';// get it from twilio //after login click Phone Numbers tab in left sidebar public string dialCode = '+1'; // Add your dial Code of your country. public Send_SMS_ControllerLead(ApexPages.StandardController controller) { hasNumber = true; } public static void Send() { String account = 'XXXXXXXXXXXXXXXXXXXXXXXXXX'; // Account SID on home tab String token = 'XXXXXXXXXXXXXXXXXXXXXXXXXX'';//AUTH Token on home tab TwilioRestClient client = new TwilioRestClient(account, token); Id leadId = ApexPages.currentPage().getParameters().get('id'); String baseUrl = URL.getSalesforceBaseUrl().toExternalForm(); Lead a = [SELECT Phone FROM Lead WHERE Id = :leadId]; if(a.Phone != null) { String phoneNumber = a.Phone; if(!phoneNumber.Contains('+1')) phoneNumber = '+1'+phoneNumber;// If by default dialCode is not //on Phone number we will ad it. System.debug('phoneNumber'+phoneNumber); Map<String,String> params = new Map<String,String> { 'To' => phoneNumber, 'From' => '+1XXXXXXXXXX', 'Body' => 'Thank you for applying with Fundwise! Next step is to get a credit report. Please check your email now for the next step.' }; TwilioSMS sms = client.getAccount().getSMSMessages().create(params); SMS_Lead__c sentSMS = new SMS_Lead__c(From__c = '+1XXXXXXXXXX',To__c =phoneNumber, Body__c = 'Thank you for applying with Fundwise! Next step is to get a credit report. Please check your email now for the next step.'); insert sentSMS; } } // This method for Trigger @future(callout=true) public static void Send(Set<Id> setId) { List<Lead> newLead = [select id,Phone from Lead where id in :setId]; String account = 'XXXXXXXXXXXXXXXXXXXXXXXXXX'; // Account SID on home tab String token = 'XXXXXXXXXXXXXXXXXXXXXXXXXX'';//AUTH Token on home tab TwilioRestClient client = new TwilioRestClient(account, token); String baseUrl = URL.getSalesforceBaseUrl().toExternalForm(); List<SMS_Lead__c> lstSMSLead = new List<SMS_Lead__c>(); for(Lead leadObj : newLead) { if(leadObj.Phone != null) { String phoneNumber = leadObj.Phone; if(!phoneNumber.Contains('+1')) phoneNumber = '+1'+phoneNumber;// If by default dialCode is not //on Phone number we will ad it. System.debug('phoneNumber'+phoneNumber); Map<String,String> params = new Map<String,String> { 'To' => phoneNumber, 'From' => '+1XXXXXXXXXX, 'Body' => 'Thank you for applying with Fundwise! Next step is to get a credit report. Please check your email now for the next step.' }; TwilioSMS sms = client.getAccount().getSMSMessages().create(params); SMS_Lead__c sentSMS = new SMS_Lead__c(From__c = '+1XXXXXXXXXXX',To__c= phoneNumber, Body__c = 'Thank you for applying with Fundwise! Next step is to get a credit report. Please check your email now for the next step.'); //insert sentSMS; lstSMSLead.add(sentSMS); } } if(lstSMSLead.size() > 0 ) { insert lstSMSLead; } } }
<pre>
setCtr.setSelected( oppList );
</pre>
That should effectively select all 20 records and the "getFieldTypeOptions" won't return null anymore. Something else later in the test might fail...
All Answers
Normally when testing code that makes REST API callouts, you would create a class that implements the HTTPRequestMock class and use it to stand in for the REST API endpoint. That way, the test code doesn't actually make a callout, and you have control over the response that is returned to the code you're testing.
All that said, you don't really know what the Twillio package is sending or expecting as a response. So you can't really spoof it with an HTTPRequestMock.
Instead, you might want to put the calls to the Twillio create() method inside an if statement that calls Test.isRunningTest(). This returns true if the code is running inside a test. Because you don't seem to use the TwillioSMS instance that's returned, you could call Twillio only if you're not in a test. By keeping it all on one line (as I do below), the line counts as covered, even though create() is not called.
<pre>
if ( ! Test.isRunningTest() ) client.getAccount().getSMSMessages().create(params);
</pre>
<pre>
trigger SMS_To_New on Lead ( after insert )
{
Send_SMS_ControllerLead.send( Trigger.newMap.keySet() );
}
public class Send_SMS_ControllerLead
{
private final String account = 'XXXXXXXXXXXXXXXXXXXXXXXXXX';
private final String token = 'XXXXXXXXXXXXXXXXXXXXXXXXXX';
private final String dialCode = '+1';
private final String fromNumber = '+1XXXXXXXXXX';
private final String defaultBody =
( 'Thank you for applying with Fundwise! '
+ 'Next step is to get a credit report. '
+ 'Please check your email now for the next step.'
);
public String smsBody { get; set; }
public Boolean hasNumber { get; set; }
public Send_SMS_ControllerLead( ApexPages.StandardController controller )
{
hasNumber = true; // not sure what this is for
}
// controller action method must not be static
public void send()
{
Id leadId = (Id) ApexPages.currentPage().getParameters().get( 'id' );
// avoid a DML exception by iterating the query results
for ( Lead lead : [SELECT Phone FROM Lead WHERE Id = :leadId] )
{
if ( lead.Phone == null ) continue;
insert sendToLead( lead, smsBody );
}
}
// This method for Trigger
@future(callout=true)
public static void send( Set<Id> setId )
{
List<SMS_Lead__c> lstSMSLead = new List<SMS_Lead__c>();
for ( Lead lead : [SELECT Phone FROM Lead WHERE Id IN :setId] )
{
if ( lead.Phone == null ) continue;
lstSMSLead.add( sendToLead( lead, defaultBody ) );
}
// there is no error doing DML on an empty list
// and it does not count against DML limits
insert lstSMSLead;
}
private SMS_Lead__c sendToLead( Lead lead, String body )
{
String phoneNumber = lead.Phone;
if ( ! phoneNumber.startsWith( dialCode ) )
{
phoneNumber = dialCode + phoneNumber;
}
Map<String,String> params = new Map<String,String>
{ 'To' => phoneNumber
, 'From' => fromNumber
, 'Body' => body
};
if ( ! Test.isRunningTest() ) (new TwilioRestClient( account, token )).getAccount().getSMSMessages().create( params );
return new SMS_Lead__c
( To__c = params.get( 'To' )
, From__c = params.get( 'From' )
, Body__c = params.get( 'Body' )
);
}
}
@isTest
public class Test_Send_SMS_ControllerLead
{
public static testMethod void testInsertLead
{
Lead testLead = new Lead
( LastName = 'Test'
, Phone = '5555555555'
);
Test.startTest();
// this should invoke the trigger and @future
insert testLead;
Test.stopTest();
List<SMS_Lead__c> smsLeads = [SELECT To__c FROM SMS_Lead__c];
System.assert( ! smsLeads.isEmpty(), 'Inserting Lead did not create SMS_Lead.' );
for ( SMS_Lead__c smsLead : smsLeads )
{
System.assertEquals( '+15555555555', smsLead.To__c, 'SMS_Lead was created incorrectly.' );
}
}
public static testMethod void testControllerExtension
{
Lead testLead = new Lead
( LastName = 'Test'
, Phone = '5555555555'
);
insert testLead;
ApexPages.StandardController controller = new ApexPages.StandardController( testLead );
Send_SMS_ControllerLead extension = new Send_SMS_ControllerLead( controller );
Test.setCurrentPage( Page.NameOfAVisualforcePage );
ApexPages.currentPage().getParameters().put( 'id', testLead.Id );
Test.startTest();
extension.smsBody = 'Test SMS';
extension.send();
Test.stopTest();
List<SMS_Lead__c> smsLeads = [SELECT To__c, Body__c FROM SMS_Lead__c];
System.assert( ! smsLeads.isEmpty(), 'Messaging Lead did not create SMS_Lead.' );
for ( SMS_Lead__c smsLead : smsLeads )
{
System.assertEquals( '+15555555555', smsLead.To__c, 'SMS_Lead was created incorrectly.' );
System.assertEquals( 'Test SMS', smsLead.Body__c, 'SMS_Lead was created incorrectly.' );
}
}
}
</pre>
I have tried everything i know.
<pre>
public static testMethod void testInsertLead()
// and
public static testMethod void testControllerExtension()
</pre>
Sorry for the typos!
<pre>
// make this method static, so it can be called from @future
private static SMS_Lead__c sendToLead( Lead lead, String body )
</pre>
New error is on the Send_SMS_ControllerLead
<pre>
private static final String account = 'XXXXXXXXXXXXXXXXXXXXXXXXXX';
private static final String token = 'XXXXXXXXXXXXXXXXXXXXXXXXXX';
private static final String dialCode = '+1';
private static final String fromNumber = '+1XXXXXXXXXX';
private static final String defaultBody =
( 'Thank you for applying with Fundwise! '
+ 'Next step is to get a credit report. '
+ 'Please check your email now for the next step.'
);
</pre>
With the TestUpdateOwner here is the code and the error at the bottom. The ID in the error doesnt exist in
<pre>
@isTest
public class TestUpdateOwner {
static testMethod void TestUpdateOwner() {
test.startTest();
Account A = new Account();
A.Name= 'Test';
insert A;
Opportunity O = new Opportunity();
O.CloseDate = Date.Today();
O.StageName = 'Test';
O.Name = 'Test';
insert O;
O.StageName = 'Underwriting';
update O;
O.Closer_Owner__c = UserInfo.getUserId();
O.StageName = 'Sales';
update O;
O.StageName = 'Funding';
update O;
O.StageName = 'Scheduling';
update O;
}
}
</pre>
Best practice is to run all tests after changing validation rules. Better yet, change the rules in a sandbox, test everything there, then deploy the new validation rules in a change set.
System.assert(controller.getFieldTypeOptions().size()>1);
"controller" isn't null, because it is created just above this line. But "controller.getFieldTypeOptions()" might be returning "null". If so, then trying to call the size() method will throw the exception you're seeing. Without seeing the MassUpdateSimpleController class, I can't tell you if or how the "getFieldTypeOptions()" method might be returning null; but that's where I would start looking. The test could (should?) be changed to do this instead:
System.assert(controller.getFieldTypeOptions() != null && controller.getFieldTypeOptions().size()>1);
That will fix the immediate problem.
System.assert(controller.getFieldTypeOptions().size()>1);
The 'controller' variable is assigned on line 145:
MassUpdateSimpleController controller = new MassUpdateSimpleController(setCtr);
But that won't be null, because it is allocating a new controller. So it must be that the 'getFieldTypeOptions()' call is returning null. That's in the controller class. Find it and figure out under what conditions it will return null. Change your test data so that it returns what you expect. Part of the problem is that the test uses "seeAllData", which means you're getting random test data from your org. You have no control over what is in the Account records you're using to test with. Much better not to use "seeAllData" and instead, create Account records specifically for the test.
Ive tried everything i can think of and it still returns error after error after error
<pre>
setCtr.setSelected( oppList );
</pre>
That should effectively select all 20 records and the "getFieldTypeOptions" won't return null anymore. Something else later in the test might fail...