+ Start a Discussion
Rick MacGuiganRick MacGuigan 

How to unit test passing an Id to child object used for a SOQL

I new to writing unit test and need to test a visualforce page that implements an extended controller. The visualforce page is called from a custom button on a parent object (Audit__c) that passes an ID for the extended controller. The ID is used to query values on the parent used to render fields on the VF page of the child (Auto_Audit_Sample_Policy__c. )

How do I pass ID's into the unit test ? Also, the parent object (Audit__c) contains several checkbox fields that the child object (Auto_Audit_Sample_Policy__c) queries thru the extended controller. For unit testing do I preset these checkbox values in the test utility class or the actual unit test ? 

This is the error message I am getting:
Error Message    System.QueryException: List has no rows for assignment to SObject
Stack Trace    Class.ParentChildExtensionAUTOsample.<init>: line 27, column 1
Class.UnitTest_Audit.testNewSample: line 37, column 1

The URL for the custom button is:
/apex/PROD_Audit_Auto_PolicySample?AccId={!Audit__c.Id}

The VF page uses the following controller extension:
<apex:page standardController="Auto_Audit_Sample_Policy__c"  extensions="ParentChildExtensionAUTOsample" > 

The extended controller code :
public with sharing class ParentChildExtensionAUTOsample {

/*
This code supports the PROD_Audiit_Auto_PolicySample visualforce page.
FUNCTION:
Receives parent ID (accID) passed via commandbutton or custom button on parent related list.
AccId must be passed via URL since we are instantiating a new object reccord which is not saved.
accID is needed to query parent fields that are used on the visualforce page for rendering.
A non list object is used for the SOQL query to the parent. The result set is used in the visualforce page for setting control variables for rendering. 
* we are always passing the parent ID to this query and using LIMIT=1 per salesforce best practices. 
The parent ID is loaded into the related list field on the instanitated object to establish relationship when saved. 
*/

public Audit__c audit{get;set;}
Auto_Audit_Sample_Policy__c record;

String accId;
@TestVisible private Apexpages.StandardController controller; 

public ParentChildExtensionAUTOsample(ApexPages.StandardController standardController)
{
//set sample to current record.
this.record = (Auto_Audit_Sample_Policy__c)standardController.getrecord();
//grab AccID passed in from URL
accID=ApexPages.currentPage().getParameters().get('AccId');
  
 audit= [SELECT Id, Name, Policy_Information__c, Policy_Number__c, Prior_Carrier__c, Expiring_Premium__c, Reinstatement_Information__c, Insured_Location__c, Agent_Information__c, Agent_City__c, Agent_Name__c, 
    Driver_Information__c, Age__c, Gender__c, Marital_Status__c, Named_Insured_Add_Driver__c, Occupation__c, Business_Use__c, Vehicle_Information__c, Model_Year__c, Vehicle_Type__c, ISO_Symbol__c, 
    Annual_Miles__c, Limit_Information__c, Liability_Limits__c, UM_Limits__c, UIM_Limits__c, UM_UIM_Limits__c, PIP_Limits__c, PIP_Deductible__c, APD_Deductible_Vehicle__c, Premium__c, Rating_Information__c, 
    MVR_Violations__c, Policy_Discounts__c, Rating_Tier__c, Credit_Scoring__c, Telematics_UBI__c, Loss_Information__c, CLUE_Report__c, Prior_Carrier_Loss_Experience__c, Company_Loss_Experience__c, Individual_Loss_Detail__c, 
    General_Information__c, Signed_Application__c, Vehicle_Photo_Information__c, Proof_of_Ownership__c, Other_Policies__c, UW_Guidelines_Followed__c, Risk_Management_Standards__c, Personal_Auto_Product__c      
    FROM Audit__c WHERE Id = :ApexPages.currentPage().getParameters().get('AccId') LIMIT 1];

//Load the parent Name (ID) into the Audit field. 
record.Audit__c = audit.Id;
}
}

Heres my unit test:
 
@isTest
private class UnitTest_Audit {
  //Test coverage for Account Creation
  static testmethod void testGetAccount() {
    Account acct = UtilityAudit.getAccount();
    insert acct;
  }

  //Test coverage for Audit Creation
  static testmethod void testGetAudit() {
    Account acct = UtilityAudit.getAccount();
    insert acct;
    Test.startTest();    
    Audit__c audit = UtilityAudit.getAudit(acct.Id);
    insert audit;
    Test.stopTest();
  }

  //Test coverage for New Audit Sample Creation (VF page) 
  static testmethod void testNewSample() {
    //initiate the VF page
    PageReference pageRef = Page.prod_audit_auto_policysample;
    Test.setcurrentPage(pageref);
      
    Account acct = UtilityAudit.getAccount();
    insert acct;
    Audit__c audit = UtilityAudit.getAudit(acct.Id);
    insert audit; 
    Auto_Audit_Sample_Policy__c sample = UtilityAudit.getAuto_Audit_Sample_Policy(audit.Id);
    insert sample;
		//set required fields
        sample.Policy_Number__c = 'sampleTest';
        sample.Insured_ZipCode__c = '99999';
		
    Test.startTest();    
 
    //create standard controller and extended controller instance    
    ApexPages.StandardController sc = new ApexPages.standardController(sample);
    ParentChildExtensionAUTOsample testPage = new ParentChildExtensionAUTOsample(sc);
    
    Test.stopTest();
  }
}

Heres my utility class for testing:
@isTest
public class UtilityAudit {
    
    //build the Account object
    public static Account getAccount() {
        Account acct = new Account();
        acct.Name = 'Unit Test Account';

        return acct;
    }

    //build the Audit object
    public static Audit__c getAudit(Id accountId) {
        Audit__c audit = new Audit__c();
        audit.Cedent_Account_CCA_PS__c = accountId;
        //set grid checkbox values. Used by Auto Sample to render VF page fields
        audit.Policy_Information__c = true;
        audit.Policy_Number__c = true;
                
        return audit;
    }

    //build the Auto Sample object
    public static Auto_Audit_Sample_Policy__c getAuto_Audit_Sample_Policy(Id AccId) {
        Auto_Audit_Sample_Policy__c samplePolicy = new Auto_Audit_Sample_Policy__c();
        samplePolicy.Audit__c = AccId;
        samplePolicy.Policy_Number__c = 'sampleTest';
        samplePolicy.Insured_ZipCode__c = '99999';
        
        return samplePolicy;
    }    
   
    
}




 
Best Answer chosen by Rick MacGuigan
jp1234jp1234
Can you try following?

Change line 28 of your test class to
 
Database.insert(audit);

and add following line BEFORE line 38 of your test class
 
Apexpages.currentPage().getParameters().put('AccId', audit.Id);

 

All Answers

jp1234jp1234
Can you try following?

Change line 28 of your test class to
 
Database.insert(audit);

and add following line BEFORE line 38 of your test class
 
Apexpages.currentPage().getParameters().put('AccId', audit.Id);

 
This was selected as the best answer
Rick MacGuiganRick MacGuigan
Thanks for the response. The unit test passed with just the line 'Apexpages.currentPage().getParameters().put('AccId', audit.Id);' inseerted. Makes sense. Still passes whe I implement Database.insert(audit); as well but not sure that is needed ? 

Also, the parent object (Audit__c) contains several checkbox fields that the child object (Auto_Audit_Sample_Policy__c) queries thru the extended controller. For unit testing do I preset these checkbox values in the test utility class or the actual unit test ? 
jp1234jp1234
If you are checking those values in the test class, then I would include in your utility class.   However, if you are not actually checking those checkbox values as part of your test and if it isn't part of the WHERE statement of your query (which seems to be the case), I wouldn't worry about putting those in.
Rick MacGuiganRick MacGuigan
Do you find using database.insert more benefiscial then using insert (http://learn4sfdc.blogspot.com/2014/01/what-is-difference-between.html)? Seems like the key difference is that database.insert will allow testing to log an error and continue.
jp1234jp1234
No, if insert works for you, I would use either way.  It used to be the case that insert or Database.insert statement didn't set the ID of the object (after insert or Database.insert, the audit record in your example would have had NULL as the ID), so the only way you could get the ID of the object after the insertion is if you used Database.insert and get it through the Database.saveresult return value.  Salesforce did change that so that Database.insert statement would set the ID aftewards, but I guess they made the same changes to insert statement as well.