0

I have a VF Page for a Custom Object that asks a User for a PIN and checks it versus a field on the Contact Object which is it's direct Parent.

This Controller Extension is used for 2 other VF Pages, one on Contact and one on Account.

The VF Page uses a non-rendered apex:outputText to reference the field on the Parent Contact.

<apex:outputText value="{!CustomObject__c.Contact_Owner__r.Security_Pin__c}" rendered="false" />

Because this Controller Extension is used with other VF Pages the field is retrieved dynamically.

When I run my test the Contact_Owner__r.Security_PIN__c field is not populating in the Controller Extension, but when I functionally test the VF Page it populates properly.

private String PINRef {get; set;} // Set in the getField() method
public String PINinput {get; set;} // User entered value

// Controller Extension Constructor
public SecurityController(ApexPages.StandardController controller)
{
    SObject obj = controller.getRecord();

    if(obj.getSObjectType() ==CustomObject__c.sObjectType)
    {
        getField('Contact_Owner__r', 'Security_PIN__c', obj);
    }else if(...)
    }
}

private void getField(String parentRelationship, String fieldAPIName, SObject obj)
{
    Contact c = (Contact)obj.getSObject(parentRelationship);
    if( null != c && c.get(fieldAPIName) != null)
    {
        PINRef = String.valueOf(c.get(fieldAPIName));
        hasPIN = true;
    }else
    {
        hasPIN = false;
    }
}

The user enters a PIN in the VF Page and clicks a button which compares the User entered value with the one on the Contact record.

public void checkPin()
{
    if(PINInput != null)
    {
        Blob inputBlob = Blob.valueOf(PINInput);
        Blob inputHash = Crypto.generateDigest('SHA1', inputBlob);
        String result = EncodingUtil.base64encode(inputHash);
        PINMatches = PINRef.equals(result);
    }
}

My test creates and inserts a base Contact record, afterwards it adds the PIN and Updates the Contact record. Then it creates the record for my Custom Object.

static testMethod void testWithTrustAccount()
{
    Contact cont = new Contact(FirstName = F_NAME, LastName = F_NAME);
    insert cont;

    Contact c = [SELECT Id FROM Contact WHERE FirstName = :F_NAME AND LastName = :F_NAME];

    String PIN = '123456';
    Blob PINBlob = blob.valueOf(PIN);
    Blob PINHash = Crypto.generateDigest('SHA1',PINBlob);
    c.Security_PIN__c = EncodingUtil.base64encode(PINHash);

    update c;

    CustomObject__c custom = new CustomObject__c(Name = 'Test Pin', Contact_Owner__c = c.Id);
    insert custom;

    Test.setCurrentPage(Page.SecurityCheckCustomObject); // This was added (1)
    ApexPages.currentPage().getParameters().put('id', custom.Id); //This was added (2).
    ApexPages.StandardController standardController = new ApexPages.StandardController(trust);

    SecurityController testController = new SecurityController(standardController);

    Test.startTest();

        testController.PINInput = '123456';
        testController.checkPin();

    Test.stopTest();

    System.assertEquals(true, testController.hasPin,
        'No PIN found via the CustomObject__c.Contact_Owner__r.Security_PIN__c relationship');
    System.assertEquals(true, testController.PINMatches,
        'The PIN did not match');
}

I suspect it has something to do with how I'm setting the VF Page in my test method. Originally I did not set it at all, but realizing I'm getting the field through the VF Page I decided to set it (1). That didn't work so I that adding the ID of the custom object might help (2), but that didn't work either.

My VF Page works when I functionally test it, but I can't get my test method to see the Security_PIN__c field.

5
  • Hey Doug, what (and where) is the error message you're getting? Commented Dec 29, 2015 at 21:10
  • @SebastianKessel I'm getting Attempt to de-reference a null object. At is happening in the checkPin() method PINRef.equals(). I'm getting the error because the if( null != c && c.get(fieldAPIName) != null) line in the getField() method is evaluating to false.
    – dBeltowski
    Commented Dec 29, 2015 at 21:26
  • I would start by adding a line in the checkPin to ensure that PINRef is not null (which could happen if hasPin == false). But I seem to be missing some of your code. I like that you abridged, but perhaps you abridged too much? Also, how is "getField" called? Commented Dec 29, 2015 at 21:29
  • One more thought, I would also use <apex:inputHidden> instead of a non-rendered <apex:outputText> Commented Dec 29, 2015 at 21:31
  • @SebastianKessel I updated my question to better explain what I'm trying to do. My issue is that PINRef is null because c.get(fieldAPIName) is coming up null. I need c.get(fieldAPIName) to not be null in my Test. You're right about the <apex:inputHidden> tag.
    – dBeltowski
    Commented Dec 29, 2015 at 21:37

1 Answer 1

2

Try changing the following lines in your test code:

    CustomObject__c custom = new CustomObject__c(Name = 'Test Pin', Contact_Owner__c = c.Id);
    insert custom;

    //New Line
    custom = [select Id, Name, Contact_Owner__r.Security_Pin__c from CustomObject__c where Id = :c.id LIMIT 1];

    Test.setCurrentPage(Page.SecurityCheckCustomObject); // This was added (1)
    ApexPages.currentPage().getParameters().put('id', custom.Id); //This was added (2).
    //Changed Line
    ApexPages.StandardController standardController = new ApexPages.StandardController(custom);
1
  • This answer will allow your controller to test correctly, but to me it seems like a work around, we should not have to query the fields to achieve a successful test,, the page should provide the fields, hence the apex:inputhidden should work, but I possibly doesn't. Surely there is another solution not requiring an explicit query, utilising the fields referred to in the VF page? Commented Jan 21, 2019 at 23:21

You must log in to answer this question.

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