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
David KassoufDavid Kassouf 

APEX Code Testing - UploadAttachmentController

Hello All,

I am sure you see requests all the time to aid in the creation, modification and testing of new APEX code from greenhorns like myself. The code below is complete and helps with a custom attachment object that replaces the standard Notes & Attachments section on Contracts. The code, object and process works great in the Sandbox environment but I am having difficulties testing the code.

I have browsed through the forums looking and have been researching online for best practices on testing APEX coding in general and have been unable to tackle the project fully. If anyone could assist, I would greatly appreciated it!

User-added image
public class UploadContractAttachmentController {
    
    public String selectedType {get;set;}
    public String description {get;set;}
    private Contract contract {get;set;} 
    public String fileName {get;set;}
    public Blob fileBody {get;set;}
    
    public UploadContractAttachmentController(ApexPages.StandardController controller) { 
        this.contract = (Contract)controller.getRecord();
    }   
    
    // creates a new Contract_Attachment__c record
    private Database.SaveResult saveCustomAttachment() {
        Contract_Attachment__c obj = new Contract_Attachment__c();
        obj.contract__c = contract.Id; 
        obj.description__c = description;
        obj.type__c = selectedType;
        // fill out cust obj fields
        return Database.insert(obj);
    }
    
    // create an actual Attachment record with the Contract_Attachment__c as parent
    private Database.SaveResult saveStandardAttachment(Id parentId) {
        Database.SaveResult result;
        
        Attachment attachment = new Attachment();
        attachment.body = this.fileBody;
        attachment.name = this.fileName;
        attachment.parentId = parentId;
        // inser the attahcment
        result = Database.insert(attachment);
        // reset the file for the view state
        fileBody = Blob.valueOf(' ');
        return result;
    }
    
    /**
    * Upload process is:
    *  1. Insert new Contract_Attachment__c record
    *  2. Insert new Attachment with the new Contract_Attachment__c record as parent
    *  3. Update the Contract_Attachment__c record with the ID of the new Attachment
    **/
    public PageReference processUpload() {
        try {
            Database.SaveResult customAttachmentResult = saveCustomAttachment();
        
            if (customAttachmentResult == null || !customAttachmentResult.isSuccess()) {
                ApexPages.AddMessage(new ApexPages.Message(ApexPages.Severity.ERROR, 
                  'Could not save attachment.'));
                return null;
            }
        
            Database.SaveResult attachmentResult = saveStandardAttachment(customAttachmentResult.getId());
        
            if (attachmentResult == null || !attachmentResult.isSuccess()) {
                ApexPages.AddMessage(new ApexPages.Message(ApexPages.Severity.ERROR, 
                  'Could not save attachment.'));            
                return null;
            } else {
                // update the custom attachment record with some attachment info
                Contract_Attachment__c customAttachment = [select id from Contract_Attachment__c where id = :customAttachmentResult.getId()];
                customAttachment.name = this.fileName;
                customAttachment.Attachment__c = attachmentResult.getId();
                update customAttachment;
            }
        
        } catch (Exception e) {
            ApexPages.AddMessages(e);
            return null;
        }
        
        return new PageReference('/'+contract.Id);
    }
    
    public PageReference back() {
        return new PageReference('/'+contract.Id);
    }     
 
}

 
Best Answer chosen by David Kassouf
Chidambar ReddyChidambar Reddy
Hi David, try the following test class
 
@isTest
public class UploadContractAttachmentController_Tests {


         @isTest static void testProcessUpload(){
                   // set the page
                    test.setCurrentPageReference(page.UploadContractAttachment);
                    //create the contract here 
                    contract c = new contract();
                    c.Status = 'Draft';
                    c.StartDate = system.today();
                    c.ContractTerm = 12;
                    insert c;

                    ApexPages.StandardController sc = new ApexPages.StandardController(c);
                    UploadContractAttachmentController ucac = new UploadContractAttachmentController(sc);
                    
                    //fill page variables
                    ucac.selectedType = 'VALUE';
                    ucac.description = 'VALUE';
                    ucac.fileName = 'FILE NAME';
                    ucac.fileBody = blob.valueOf('abcd');
                    test.startTest();
                    //click the button 
                    ucac.processUpload();
                    test.stopTest();

          }
 }

 

All Answers

Chidambar ReddyChidambar Reddy
Hi David
 
@isTest
public class UploadContractAttachmentController_Tests {


         @isTest static void testProcessUpload(){
                   // set the page
                    test.setCurrentPageReference(page.PAGENAME);
                    //create the contract here 
                    contract c = new contract();
                    ApexPages.StandardController sc = new ApexPages.StandardController(c);
                    UploadContractAttachmentController ucac = new UploadContractAttachmentController(sc);
                    // fill contract details
                    ucac.contract.FIELD = VALUE;
                    //fill page variables
                    ucac.selectedType = 'VALUE';
                    ucac.description = 'VALUE';
                    ucac.fileName = 'FILE NAME';
                    ucac.fileBody = blob.valueOf('abcd');
                    test.startTest();
                    //click the button 
                    ucac.processUpload();
                    test.stopTest();

          }

}


Thanks 
Choose it as best answer if it has helped you
 
David KassoufDavid Kassouf
Hello Chidambar,

Thank you for providing the test code above. The test code works but, is providing about 45% coverage. Which is a great improvement over what I was able to conjure up but it still leaves me a little short. I appreciate your help and am wondering what I am missing.
 
@isTest
public class UploadContractAttachmentController_Tests {


         @isTest static void testProcessUpload(){
                   // set the page
                    test.setCurrentPageReference(page.UploadContractAttachment);
                    //create the contract here 
                    contract c = new contract();
                    ApexPages.StandardController sc = new ApexPages.StandardController(c);
                    UploadContractAttachmentController ucac = new UploadContractAttachmentController(sc);
                    // fill contract details
                    ucac.contract.Status = 'Draft';
                    ucac.contract.StartDate = system.today();
                    ucac.contract.ContractTerm = 12;
                    //fill page variables
                    ucac.selectedType = 'VALUE';
                    ucac.description = 'VALUE';
                    ucac.fileName = 'FILE NAME';
                    ucac.fileBody = blob.valueOf('abcd');
                    test.startTest();
                    //click the button 
                    ucac.processUpload();
                    test.stopTest();

          }
 }

 
Chidambar ReddyChidambar Reddy
Hi David

add ucas.back() before 24th Line,

and let me know which lines are covered in ProcessUpload() method
David KassoufDavid Kassouf

Chidambar,

Thank you again for your help! I have added the ucac.back() before line 24 and there is now 50% Coverage. From what I can see in the developer’s console, the code below is not covered.
 
// create an actual Attachment record with the Contract_Attachment__c as parent
    private Database.SaveResult saveStandardAttachment(Id parentId) {
        Database.SaveResult result;
        
        Attachment attachment = new Attachment();
        attachment.body = this.fileBody;
        attachment.name = this.fileName;
        attachment.parentId = parentId;
        // insert the attachment
        result = Database.insert(attachment);
        // reset the file for the view state
        fileBody = Blob.valueOf(' ');
        return result;
    }

            if (customAttachmentResult == null || !customAttachmentResult.isSuccess()) {
                ApexPages.AddMessage(new ApexPages.Message(ApexPages.Severity.ERROR, 
                  'Could not save attachment.'));
                return null;
            }
        
            Database.SaveResult attachmentResult = saveStandardAttachment(customAttachmentResult.getId());
        
            if (attachmentResult == null || !attachmentResult.isSuccess()) {
                ApexPages.AddMessage(new ApexPages.Message(ApexPages.Severity.ERROR, 
                  'Could not save attachment.'));            
                return null;
            } else {
                // update the custom attachment record with some attachment info
                Contract_Attachment__c customAttachment = [select id from Contract_Attachment__c where id = :customAttachmentResult.getId()];
                customAttachment.name = this.fileName;
                customAttachment.Attachment__c = attachmentResult.getId();
                update customAttachment;
            }

        return new PageReference('/'+contract.Id);
    }

 
David KassoufDavid Kassouf
Hello Chidambar,

I reread your last post and the lines that are covered in ProcessUpload() method are listed below.
 
* Covered Section 1
 
    public String selectedType {get;set;}
    public String description {get;set;}
    private Contract contract {get;set;} 
    public String fileName {get;set;}
    public Blob fileBody {get;set;}
    
    public UploadContractAttachmentController(ApexPages.StandardController controller) { 
        this.contract = (Contract)controller.getRecord();
    }   
    
    // creates a new Contract_Attachment__c record
    private Database.SaveResult saveCustomAttachment() {
        Contract_Attachment__c obj = new Contract_Attachment__c();
        obj.contract__c = contract.Id; 
        obj.description__c = description;
        obj.type__c = selectedType;
        // fill out cust obj fields
        return Database.insert(obj);
    }


 public PageReference processUpload() {
        try {
            Database.Save   Result customAttachmentResult = saveCustomAttachment();

        } catch (Exception e) {
            ApexPages.AddMessages(e);
            return null;
        }

 public PageReference back() {
        return new PageReference('/'+contract.Id);
    }     
 
}

 
Chidambar ReddyChidambar Reddy
Hi David, 

there re is an exception being thrown while inserting contract attachment 

you need check what was it, by enabling debug logs to your user , run your test > go to debug log > find the exception being thrown 
David KassoufDavid Kassouf
Hello Chidambar,

I added myself to the monitored users under debug logs and ran the UploadContractAttachmentController_Tests. All of the debug logs seemed to be sucessfull and did not throw up any errors.

User-added image
Chidambar ReddyChidambar Reddy
Hi David,

It is like displaying error messages in the visualforce page, i.e, you are hadling exceptions (instead of coming error mails to you) 

You need to open the log, and find the errors
 
catch (Exception e) {
           ApexPages.AddMessages(e);
           return null;
}
Replace above lines in your class with
 
catch (Exception e) {
           ApexPages.AddMessages(e);
           System.debug('Error is Here:'+e.getMessage());
           return null;
}

and Run the test class again (make sure debug logs are with your user)

open the log, use Ctrl+F and search 'Error is Here' (without single quotes)

 
David KassoufDavid Kassouf

Hello Chidambar,

I followed exactly what you stated above, thank you for the step by step instructions, and found the following error.

17:17:40.128 (128797367)|VF_PAGE_MESSAGE|Required fields are missing: [Contract__c]
17:17:40.128 (128906135)|EXCEPTION_THROWN|[20]|System.DmlException: Insert failed. First exception on row 0; first error: REQUIRED_FIELD_MISSING, Required fields are missing: [Contract__c]: [Contract__c]
17:17:40.130 (130569895)|SYSTEM_METHOD_EXIT|[20]|Database.insert(SObject)
17:17:40.130 (130597730)|METHOD_EXIT|[46]|01pM00000003J71|UploadContractAttachmentController.saveCustomAttachment()
17:17:40.130 (130683864)|SYSTEM_METHOD_ENTRY|[69]|ApexPages.addMessages(APEX_OBJECT)
17:17:40.130 (130868872)|SYSTEM_METHOD_EXIT|[69]|ApexPages.addMessages(APEX_OBJECT)
17:17:40.130 (130909851)|SYSTEM_METHOD_ENTRY|[70]|System.DmlException.getMessage()
17:17:40.130 (130966682)|SYSTEM_METHOD_EXIT|[70]|System.DmlException.getMessage()
17:17:40.131 (131026708)|SYSTEM_METHOD_ENTRY|[70]|System.debug(ANY)
17:17:40.131 (131044793)|USER_DEBUG|[70]|DEBUG|Error is Here:Insert failed. First exception on row 0; first error: REQUIRED_FIELD_MISSING, Required fields are missing: [Contract__c]: [Contract__c]
David KassoufDavid Kassouf
Hello Chidambar,

Contract__c is the Master-Detail(Contract) field that links the attachment record to the associated contract. In the normal workflow I would create a new contact record, which would create the Contract Number. This contract number is used in the Contract__c field to link the new attachment to the record.  
  
Chidambar ReddyChidambar Reddy
Hi David, try the following test class
 
@isTest
public class UploadContractAttachmentController_Tests {


         @isTest static void testProcessUpload(){
                   // set the page
                    test.setCurrentPageReference(page.UploadContractAttachment);
                    //create the contract here 
                    contract c = new contract();
                    c.Status = 'Draft';
                    c.StartDate = system.today();
                    c.ContractTerm = 12;
                    insert c;

                    ApexPages.StandardController sc = new ApexPages.StandardController(c);
                    UploadContractAttachmentController ucac = new UploadContractAttachmentController(sc);
                    
                    //fill page variables
                    ucac.selectedType = 'VALUE';
                    ucac.description = 'VALUE';
                    ucac.fileName = 'FILE NAME';
                    ucac.fileBody = blob.valueOf('abcd');
                    test.startTest();
                    //click the button 
                    ucac.processUpload();
                    test.stopTest();

          }
 }

 
This was selected as the best answer
David KassoufDavid Kassouf
Hello Chidambar,

I added the updated test class to the sandbox enviroment and made one more addition when an error flaged. The test works great and provides 78% code coverage. Thank you so much for you help, I really could not have done any of this with out it.
 
@isTest
public class Test_UploadContractAttachmentController {


         @isTest static void testProcessUpload(){
                   // set the page
                    test.setCurrentPageReference(page.UploadContractAttachment);
                    //create the account here 
                    Account a = new Account();
                    a.Name = 'Test';
                    a.Type = 'Internal';
                    insert a;
             
                    //create the contract here 
                    contract c = new contract();
                    c.AccountId = a.id;
                    c.Status = 'Draft';
                    c.StartDate = system.today();
                    c.ContractTerm = 12;
                    insert c;

                    ApexPages.StandardController sc = new ApexPages.StandardController(c);
                    UploadContractAttachmentController ucac = new UploadContractAttachmentController(sc);
                    
                    //fill page variables
                    ucac.selectedType = 'VALUE';
                    ucac.description = 'VALUE';
                    ucac.fileName = 'FILE NAME';
                    ucac.fileBody = blob.valueOf('abcd');
                    test.startTest();
                    //click the button 
                    ucac.processUpload();
                    test.stopTest();

          }
 }