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
Tolby HuntTolby 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 - 
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;
        }  
    }
}

 
Best Answer chosen by Tolby Hunt
Glyn Anderson 3Glyn Anderson 3
Tolby,  I found the MassUpdateSimpleController class (and the test class) on GitHub (https://github.com/ForceDotComLabs/Mass-Update-And-Mass-Edit/blob/master/src/classes/MassUpdateSimpleController.cls).  I don't know if your version of the class has been modified, but your test class has.  The original does not include the "testOpportunityInRelatedList" test method, which is the one that is failing.  The method, "getFieldTypeOptions", called on line 148, returns null if no records are selected in the set controller.  Notice that the other test methods all call "setSelected" on the set controller immediately after it is instantiated.  The failing test does not select any records.  You can fix this in the failing test by inserting a line after line 143:

<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

Glyn Anderson 3Glyn Anderson 3
Tolby,

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>
Glyn Anderson 3Glyn Anderson 3
This is a complete example.  Use whatever parts of this you need.  I refactored the class, just to give you some ideas.  The test class should give you 100% coverage.  Disclaimer:  This code is untested and may contain typos.

<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>
Tolby HuntTolby Hunt
With the @isTest it is saying Error: Compile Error: unexpected token: 'Lead' at line 6 column 9
 
@isTest
public class Test_Send_SMS_ControllerLead
{
    public static testMethod void testInsertLead
    {
        Lead testLead = new Lead
        (   LastName = 'Test'
        ,   Phone = '8018348750'
        );

        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( '+18018348750', smsLead.To__c, 'SMS_Lead was created incorrectly.' );
        }
    }

    public static testMethod void testControllerExtension
    {
        Lead testLead = new Lead
        (   LastName = 'Test'
        ,   Phone = '8018348750'
        );
        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( '+18018348750', smsLead.To__c, 'SMS_Lead was created incorrectly.' );
            System.assertEquals( 'Test SMS', smsLead.Body__c, 'SMS_Lead was created incorrectly.' );
        }
    }
}

I have tried everything i know.
Glyn Anderson 3Glyn Anderson 3
Tolby, It was late last night when I wrote that, and I made a stupid mistake.  The method declarations need to have empty parentheses on them:

<pre>
    public static testMethod void testInsertLead()
// and
    public static testMethod void testControllerExtension()
</pre>

Sorry for the typos!
Tolby HuntTolby Hunt
I didnt catch it either! now im having the issue of Error: Compile Error: Static method cannot be referenced from a non static context: void Send_SMS_ControllerLead.Send() at line 41 column 19
Glyn Anderson 3Glyn Anderson 3
My fault again.  We're mixing static and non-static methods.  Controller methods must be non-static, while @future methods must be static.  Either type can call static methods, but static methods can't call non-static methods (without instantiating the class).  To fix this error, make 'sendToLead' be static.

<pre>
    // make this method static, so it can be called from @future
    private static SMS_Lead__c sendToLead( Lead lead, String body )
</pre>
 
Tolby HuntTolby Hunt
Keeps popping up new errors. Sorry i really am new to this and am trying to get ahold of all of it.

New error is on the Send_SMS_ControllerLead
Error: Compile Error: Variable does not exist: defaultBody at line 44 column 47

 
Glyn Anderson 3Glyn Anderson 3
More "static" issues.  Make all the String constants static:

<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>
Tolby HuntTolby Hunt
okay, ive got all the way to deploy but when i try to deploy i get errors....
 
MassUpdateSimpleControllerTest	

testOpportunityInRelatedList	

System.NullPointerException: Attempt to de-reference a null object 
Stack Trace: Class.MassUpdateSimpleControllerTest.testOpportunityInRelatedList: line 148, column 1



Test_Send_SMS_ControllerLead	

testControllerExtension	

System.AssertException: Assertion Failed: Messaging Lead did not create SMS_Lead. 
Stack Trace: Class.Test_Send_SMS_ControllerLead.testControllerExtension: line 45, column 1



Test_Send_SMS_ControllerLead

	testInsertLead	

System.AssertException: Assertion Failed: Inserting Lead did not create SMS_Lead. 
Stack Trace: Class.Test_Send_SMS_ControllerLead.testInsertLead: line 18, column 1



TestUpdateOwner	

TestUpdateOwner	

System.DmlException: Update failed. First exception on row 0 with id 00646000006RcuWAAS; first error: FIELD_CUSTOM_VALIDATION_EXCEPTION, You must assign a Closer Owner before changing the stage to Sales: [Closer_Owner__c] 
Stack Trace: Class.TestUpdateOwner.TestUpdateOwner: line 22, column 1

 
Glyn Anderson 3Glyn Anderson 3
I assume you're compiling to a sandbox?  Have you tried running the test in the sandbox?  Go to Setup | Develop | Apex Test Execution, select  the Test_Send_SMS_ControllerLead test.  You can experiment with the code until the test works, or to find out what's going on.  If you add System.debug() statements into the test, you can run the test with Developer Console open and you'll have the debug logs to look at.  (You can also run the test from within Developer Console.)  I'm staring at the code and can't see how it would fail to insert the SMS_Lead__c records.  If you comment out those asserts, the test will either pass (even though the code may or may not work) or fail (because the records WERE inserted but the fields are wrong - you could force this to happen).  After running the test, you can open the class in Developer Console to see which lines were executed.  I would be interested to know whether the insert statements are executed.  The asserts are claining that the SMS_Lead__c records were not inserted; but I can't see how that would be the case.
Tolby HuntTolby Hunt
This is the error i am getting from Test_Send_SMS_ControllerLead 
System.AssertException: Assertion Failed: SMS_Lead was created incorrectly.: Expected: Test SMS, Actual: Thank you for applying with Fundwise! Next step is to get a credit report. Please check your email now for the next step.
Tolby HuntTolby Hunt
Okay so its something in my Production org. Im getting these errors and have no idea how to fix them...


With the TestUpdateOwner here is the code and the error at the bottom.  The ID in the error doesnt exist in 
@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.StageName = 'Sales';
        update O;

        O.StageName = 'Funding';
        update O;

        O.StageName = 'Scheduling';
        update O;


        
        
   }
}





System.DmlException: Update failed. First exception on row 0 with id 00646000006RdGIAA0; first error: FIELD_CUSTOM_VALIDATION_EXCEPTION, You must assign a Closer Owner before changing the stage to Sales: [Closer_Owner__c]

 
Tolby HuntTolby Hunt
And also the MassUpdateSimpleControllerTest . Here is the code and the error. It looks like i cannot even edit these. 
 
/**
 * This class contains unit tests for validating the behavior of MassUpdateController
 * and triggers.
 */
@isTest
private class MassUpdateSimpleControllerTest {


    static testMethod void singleUpdateTest() {
      Opportunity o = new Opportunity();
      List<Opportunity> oppList = [SELECT name FROM Opportunity LIMIT 20];
      
      ApexPages.StandardSetController setCtr = new ApexPages.StandardSetController(oppList);
      setCtr.setSelected(new Opportunity[]{o});
        MassUpdateSimpleController controller = new MassUpdateSimpleController(setCtr);
    System.assertEquals(1, controller.getRecordSize());
    
    System.assert(controller.getFieldTypeOptions().size()>1);
    
    system.assertEquals(1, controller.objsToUpdate.size());
    
    String value = '123test';
    controller.fieldName='name';
    controller.valueToUpdate=value;  
    //controller.convertedFieldData = controller.convertUserInputToFieldData();  
    controller.step4();
    controller.step5();
    
    System.assert(o.name==value);
    
      value ='123';
      controller.step3();
      controller.fieldName='amount';
      controller.valueToUpdate=value;  
      controller.step4();
      controller.step5();
      
      System.assert(o.amount==decimal.valueOf(value));
      
/*      value ='true';
      controller.fieldName='IsPrivate';
      controller.step3();
      controller.valueToUpdate=value;    
      controller.step4();
      controller.step5();
      
      System.assert(o.IsPrivate); */
      // make sure no exception from display tips
      System.assertEquals(controller.getFieldInfoToDisplay()!=null,true);
            
      value ='2009-4-7';
      controller.fieldName='CloseDate';
      controller.valueToUpdate=value;    
      controller.step4();
      controller.step5();
      System.assert(o.CloseDate==Date.valueOf(value));
      
      value ='Closed';
      controller.fieldName='StageName';
      controller.valueToUpdate=value;    
      controller.step4();
      controller.step5();
      System.assert(o.StageName=='Closed');
    }
    
 /*   static testMethod void massUpdateAsStandardUserTest() {
      
      Profile p = [select id from profile where name='Standard User'];
        User u = new User(alias = 'standt', email='standarduser@testorg.com',
          emailencodingkey='UTF-8', lastname='Testing', languagelocalekey='en_US',
          localesidkey='en_US', profileid = p.Id,
          timezonesidkey='America/Los_Angeles', username='standarduser@test.com');
      
      System.runAs(u) {
        Opportunity o = new Opportunity();
        List<Opportunity> oppList = [SELECT name FROM Opportunity LIMIT 20];
      
        ApexPages.StandardSetController setCtr = new ApexPages.StandardSetController(oppList);
        setCtr.setSelected(new Opportunity[]{o});
          MassUpdateSimpleController controller = new MassUpdateSimpleController(setCtr);
      System.assertEquals(1, controller.getRecordSize());
    
      System.assert(controller.getFieldTypeOptions().size()>1);
    
      system.assertEquals(1, controller.objsToUpdate.size());
    
      String value = '123test';
      controller.fieldName='name';
      controller.valueToUpdate=value;    
      controller.save();
    
      System.assert(o.name==value);
     
      }
    }  */
    
    static testMethod void linkTest() {
      Opportunity o = new Opportunity();
      List<Opportunity> oppList = [SELECT name FROM Opportunity LIMIT 20];
      
      ApexPages.StandardSetController setCtr = new ApexPages.StandardSetController(oppList);
      setCtr.setSelected(new Opportunity[]{o});
        MassUpdateSimpleController controller = new MassUpdateSimpleController(setCtr);
    
    // verify following exceptions will not cause exception
    System.assert(controller.step1()!=null);
    System.assert(controller.step2()!=null);
        controller.getFieldTypeOptions();
    System.assert(controller.step3()!=null);
    System.assert(controller.step4()!=null);
    System.assert(controller.step5()!=null);
    //System.assert(controller.cancel()!=null);
    
    System.assert(controller.getFieldTypeOptions()!=null);
    }
    
    static testMethod void fieldTest() {
      
      List<Opportunity> oppList = new Opportunity[]{};
      
      ApexPages.StandardSetController setCtr = new ApexPages.StandardSetController(oppList);
        MassUpdateSimpleController controller = new MassUpdateSimpleController(setCtr);
        System.assert(controller.cancel()!=null);
    System.assert(controller.getFieldTypeOptions()==null);
    }
    
    static testMethod void miscTest() {
      
      List<Opportunity> oppList = new Opportunity[]{};
      
      ApexPages.StandardSetController setCtr = new ApexPages.StandardSetController(oppList);
        MassUpdateSimpleController controller = new MassUpdateSimpleController(setCtr);
    
    System.assert(controller.getNow(true)!=null);
    System.assert(controller.getNow(false)!=null);
    System.assert(controller.getRecordSize()==0);
    System.assert(controller.getPicklistValues()==null);
    }
    
    @isTest(SeeAllData=true)
    static void testOpportunityInRelatedList(){
        List<Opportunity> oppList = [SELECT name, AccountId FROM Opportunity LIMIT 20];
        ApexPages.StandardSetController setCtr = new ApexPages.StandardSetController(oppList);
        apexpages.currentpage().getparameters().put('id' , oppList.get(0).AccountId);
        MassUpdateSimpleController controller = new MassUpdateSimpleController(setCtr);
        System.debug('list: ' + oppList);
        
        System.assert(controller.getFieldTypeOptions().size()>1);
    
    //system.assertEquals(1, controller.objsToUpdate.size());
    
    String value = '123test';
    controller.fieldName='name';
    controller.valueToUpdate=value;  
    //controller.convertedFieldData = controller.convertUserInputToFieldData();  
    controller.lexstep4();
    controller.lexstep5();
    List<Opportunity> selectList = (List<Opportunity>)setCtr.getSelected();
    System.assert(selectList.get(0).name==value);
        System.assert(controller.displayTexField=='true');
    System.assert(controller.displayCheckBox=='false');
        System.assert(controller.displayPicklist=='false');
        System.assert(controller.displayTextArea=='false');
        
         value ='Closed';
        controller.lexstep3();
      controller.fieldName='StageName';
      controller.valueToUpdate=value;    
      controller.lexstep4();
      controller.lexstep5();
      System.assert(selectList.get(0).StageName=='Closed');
        System.assert(controller.displayTexField=='false');
    System.assert(controller.displayCheckBox=='false');
        System.assert(controller.displayPicklist=='true');
        System.assert(controller.displayTextArea=='false');
      
        
    }
}









System.NullPointerException: Attempt to de-reference a null object
Class.MassUpdateSimpleControllerTest.testOpportunityInRelatedList: line 148, column 1

 
Glyn Anderson 3Glyn Anderson 3
For the TestUpdateOwner class, try adding a Closer Owner before setting the stage to Sales (line 21, below).

<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>
Glyn Anderson 3Glyn Anderson 3
I should add that this is a common occurence.  Someone will add a validation rule in production without considering how it might impact test execution.  Then, tests no longer work and you can't deploy anything...

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.
Glyn Anderson 3Glyn Anderson 3
For the MassUpdateSimpleControllerTest class, the offending line appears to be:

        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.
Tolby HuntTolby Hunt
So how do i fix this so i can deploy things? Because im unable to change the TestUpdateOwner in the active org where the error occurs.
Tolby HuntTolby Hunt
Also cannot change anything with  MassUpdateSimpleControllerTest
Glyn Anderson 3Glyn Anderson 3
Fix them in the sandbox where you've developed your other code, and deploy everything together in the same change set.
Tolby HuntTolby Hunt
Okay so with this issue i have updated the TestOwnerUpdate and the MassUpdateSimpleControllerTest files but im still receiving this error and It says i only have 65% code coverage 
System.NullPointerException: Attempt to de-reference a null object 
Stack Trace: Class.MassUpdateSimpleControllerTest.testOpportunityInRelatedList: line 148, column 1
Glyn Anderson 3Glyn Anderson 3
It is impossible for me to debug test and code coverage issues in your org that are preventing deployment.  This is something that you need to work through as a developer.  Look at line 148 of the MassUpdateSimpleControllerTest class and see what could possibly be null.  Then work back from there to figure out where it should be getting assigned a value.  Keep working backward until you determine how it is being assigned a null value.  Then fix the problem.  It's probably an issue with the data that's being created for the test.  But you can't really expect anyone to tell you what's happening with just a class name and a line number.  I'm happy to help; but you really need to be able to troubleshoot a null pointer exception on your own.
Glyn Anderson 3Glyn Anderson 3
Line 148 is:

        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.
Tolby HuntTolby Hunt
See i dont know what i should be returning. i didnt create this and i dont have any idea who did or why we have it in our org.
Ive tried everything i can think of and it still returns error after error after error
Glyn Anderson 3Glyn Anderson 3
Tolby,  I found the MassUpdateSimpleController class (and the test class) on GitHub (https://github.com/ForceDotComLabs/Mass-Update-And-Mass-Edit/blob/master/src/classes/MassUpdateSimpleController.cls).  I don't know if your version of the class has been modified, but your test class has.  The original does not include the "testOpportunityInRelatedList" test method, which is the one that is failing.  The method, "getFieldTypeOptions", called on line 148, returns null if no records are selected in the set controller.  Notice that the other test methods all call "setSelected" on the set controller immediately after it is instantiated.  The failing test does not select any records.  You can fix this in the failing test by inserting a line after line 143:

<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...
This was selected as the best answer
Tolby HuntTolby Hunt
Youre amazing! Thank you so much!