-1

I have been trying for about a week to figure out how to write a test method that will increase my code coverage and cannot figure it out. This is the code I have.

public class ConvertToVolunteerJob {

    private Lead lead;
    private Case newCase;
    private Contact contact;
    private Account account;

    public ConvertToVolunteerJob(ApexPages.StandardController controller) {
        lead = [SELECT 
                    Id,
                    Status,
                    Existing_Contact_Record__c,
                    FirstName,
                    LastName,
                    Street,
                    City,
                    State,
                    PostalCode,
                    Country,
                    Email,
                    Phone,
                    Salutation,
                    Title,
                    Description,
                    Birthdate__c,
                    Emergency_Contact_Name__c,
                    Emergency_Contact_Phone_Number__c,
                    Gender__c,
                    Race__c,
                    Social_Security_Number__c,
                    LeadSource,
                    Barriers__c,
                    Referring_Agency_ID__c,
                    Disability__c,
                    Household_Veteran_Status__c,
                    Previous_Client__c,
                    Referral_Date__c,
                    Referring_Agency__c,
                    Referring_Counselor__c,
                    Service_Related_Disability__c,
                    Veteran_Status__c,
                    Program__c,
                    Intake_Type__c,
                    Enrolled_Programs__c,
                    Skills_Needed__c,
                    Campaign__c,
                    Location__c,
                    Total_Hours_Due__c,
                    Number_of_Hours_Due_Per_Week__c,
                    Name,
                    Primary_Point_of_Contact__c

                FROM Lead  
                WHERE Id = :controller.getRecord().Id];
    }

    public PageReference cancel() {
        PageReference pg = new PageReference('/' + lead.Id);
        pg.setRedirect(true);
        return pg;
    }

    public PageReference process() {
        if (lead.Status == 'Closed - Converted to Case') {
            ApexPages.addMessage(new ApexPages.Message(ApexPages.Severity.ERROR, 'You cannot convert a Referral that has already been converted. Instead, clone this Referral, change the status to New, and then convert the new Referral to a Case.'));
            return null;
        }

        if (lead.Existing_Contact_Record__c != null) {
            contact = [SELECT Id, AccountId FROM Contact WHERE Id = :lead.Existing_Contact_Record__c];
            account = new Account(Id = contact.AccountId);
        } else {

            causeview__BatchSettings__c settings = causeview__BatchSettings__c.getInstance('Default');
            if (settings==null) 
                system.debug('batch setting was not found');
            else {
               account = new Account(Id=settings.causeview__BucketAccountId__c);
               contact = new Contact(AccountId = settings.causeview__BucketAccountId__c);
            }
        }



        contact.FirstName = lead.FirstName;
        contact.LastName = lead.LastName;
        contact.MailingStreet = lead.Street;
        contact.MailingCity = lead.City;
        contact.MailingState = lead.State;
        contact.MailingPostalCode = lead.PostalCode;
        contact.MailingCountry = lead.Country;
        contact.Email = lead.Email;
        contact.Phone = lead.Phone;
        contact.Salutation = lead.Salutation;
        contact.Title = lead.Title;
        contact.Birthdate = lead.Birthdate__c;
        contact.Emergency_Contact_Name__c = lead.Emergency_Contact_Name__c;
        contact.Emergency_Contact_Phone_Number__c = lead.Emergency_Contact_Phone_Number__c;
        contact.Gender__c = lead.Gender__c;
        contact.Race__c = lead.Race__c;
        contact.Social_Security_Number__c = lead.Social_Security_Number__c;
        contact.LeadSource = lead.LeadSource;
        upsert contact;


        RecordType rc = [SELECT Id FROM RecordType WHERE Name = :lead.Program__c];
        newCase = new Case(
            RecordTypeId = rc.Id,
            Related_Referral_Record__c = lead.Id,
            Status = 'Open',
            Opened_Date__c = Date.Today(),

            Barriers__c = lead.Barriers__c,
            Referring_Agency_ID__c = lead.Referring_Agency_ID__c,
            Disability__c = lead.Disability__c,
            Household_Veteran_Status__c = lead.Household_Veteran_Status__c,
            Previous_Client__c = lead.Previous_Client__c,
            Referral_Date__c = lead.Referral_Date__c,
            Referring_Agency__c = lead.Referring_Agency__c,
            Referring_Counselor__c = lead.Referring_Counselor__c,
            Service_Related_Disability__c = lead.Service_Related_Disability__c,
            Veteran_Status__c = lead.Veteran_Status__c,
            Description = lead.Description,
            Enrolled_Programs__c = lead.Enrolled_Programs__c,

            ContactId = contact.Id,
            AccountId = account.Id
        );


        lead.Existing_Contact_Record__c = contact.Id;
        lead.Linked_Case__c = newCase.Id;
        lead.Status = 'Closed - Converted to Case';
        update lead;

        RecordType intake = [SELECT Id FROM RecordType WHERE Name = 'Intake'];
        Services_ASR__c service = new Services_ASR__c(
            RecordTypeId = intake.Id,
            Case__c = newCase.Id,
            Date__c = Date.Today(),
            Program_Type__c = lead.Program__c,
            Type__c = lead.Intake_Type__c
        );

        GW_Volunteers__Volunteer_Job__c Volunteer_Job = new GW_Volunteers__Volunteer_Job__c(
            GW_Volunteers__Campaign__c = lead.Campaign__c,
            Location__c = lead.Location__c,
            Total_Hours_Due__c = lead.Total_Hours_Due__c,
            Number_of_Hours_Due_Per_Week__c = lead.Number_of_Hours_Due_Per_Week__c,
            GW_Volunteers__Skills_Needed__c = lead.Skills_Needed__c,
            Primary_Point_of_Contact__c = contact.id,
            Name = contact.FirstName
        );

        insert Volunteer_Job;



        PageReference pg = new PageReference('/a09/o');
        pg.setRedirect(true);
        return pg;
    }   

}

I honestly don't know if you are supposed to write test methods within the same class or create a whole new apex class for it. Any help would be much appreciated.

2

1 Answer 1

4

Here is my feedback help you out with writing the code and testing it. I am not saying these are the best practices, but this is what I have learned along the way. I believe it is relevant to write unit tests not to get the minimum code coverage but to actually test the code. Good testing also ensures that code development follows the best practices.

  1. Constructors should be fast and not depend on data retrieval (so data does not have to be set up every time constructor is called). Thus, use the lazy load to get data from DB the first time the lead variable is accessed:

    public class ConvertToVolunteerJob { Id leadId;

    @TestVisible
    Lead lead {
        get {
            if (lead == null) {
                lead = fetchLead();
            }
            return lead;
        }
        set;
    }
    
    public ConvertToVolunteerJob(ApexPages.StandardController controller) {
        leadId = controller.getId();
    }
    
    Lead fetchLead() {
        lead = [SELECT ... 
            FROM Lead
            WHERE id = :leadId];
    }
    

    }

It is up to you to decide if you want to have precondition in the constructor to check if leadId != null and then raise the error (VF error that displays only the error) or check this in another method and then use ApexMessage.addMessage for better error display.

  1. Instead of having lots of code in the process() method, split these statements into separate methods and then individually test those methods in the test class ensuring they return the expected output. I can see that at least 3-4 methods can be created from process() method and tested separately. For example, create a method to build and return GW_Volunteers__Volunteer_Job__c and then test in a test method to ensure fields/properties on the object are set as expected.

Actually, it is better to create a new class *Service for these methods to be called from the controller and test the Service separately.

  1. Instead of hard-coding anything, and in this case the SObject prefix, use getKeyPrefix() to obtain it (especially if this is a new object in your sandbox since the prefix will differ on different orgs until promoted to the PROD and then refreshed from there).

  2. When testing, I follow the next approach:

    • setup data,
    • act (call the methods) and
    • assert that output is as expected.

Just calling methods to have the minimal code coverage is not testing.

Also, it is best to follow Test Driven Development when developing ensuring every use case is covered. I know this can be hard to do when starting to write code but it pays off to apply it wrt code and test quality.

  1. You can omit the "private" keyword for a variable since it is set like that unless specified otherwise. Set "public" variables/methods only when they are required to be accessed from other classes/pages. Use "@TestVisible" if the variable/method is required to be tested separately from the calling public method 9some developers actually avoid using this keyword and only test public methods).

Sample test class:

@isTest
class ConvertToVolunteerJobTests {
    static ConvertToVolunteerJob contr;

    @isTest
    static void fetchLead_shouldReturnLead_whenLeadExistsInDB() {
        Lead lead = new Lead(....);
        insert lead;

        contr = new ConvertToVolunteerJob(new ApexPages.StandardController(lead));

        System.assertNotEquals(null, contr.lead);
        System.assertEquals(lead.name, contr.lead.name);
        // more asserts if required
    }

    @isTest
    static void fetchLead_shouldRaiseException_whenLeadDoesNotExistInDB() {
    .....
    }
}
  1. Since you are using the standard controller and this is the extension on the VF page, then you do not need to implement the cancel method. It is already done in Force.com platform and it will display the Lead detail page when called.

Here are few links that helped me write better tests: http://misko.hevery.com/ https://www.youtube.com/playlist?list=PL693EFD059797C21E

Hope this will be of help to write better tests.

1
  • 1
    lots of great tips in there, nice answer Oct 23, 2014 at 22:59

You must log in to answer this question.

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