5

I have created a custom Visualforce component.

It is backed by a custom controller.

I am struggling to write unit tests for it.

The limited VisualForce documentation indicates that to test it I should:

  1. put the component in a page eg <apex:page standardController='Lead'><c:Component></c:Component></apex:page>
  2. call Test.setCurrentPage(Page.TestPage)
  3. Set Page parameters `ApexPages.currentPage().getParameters().put('Id', lead.Id);
  4. Instantiate an instance of the controller for the component ComponentController cont = new ComponentController()

And then I should be able to use the controller as though it backed the VF component as included in that page.

But for whatever reason, when I do that in a test, the ComponentController does not reflect the state it should have if it was being used in that page. It seems a bit magical to assume it would work this way, and there is no documentation indicating that it should or should not, so I am pretty confused as to what to do.

For Reference, my actual code looks like this.

<apex:page standardController="Lead" showHeader="false" >
    <c:CustomComponent record="Lead" />
</apex:page>

<apex:component controller="CustomComponentController" allowDML="true">
    <apex:attribute 
        name="record"
        description="Which Record type"
        type="Object"
        required="true"
        assignTo="{!sObj}" />
    {!recType}
</apex:component>

public class CustomComponentController {
    public Object sObj {get; set;}

    public String getRecType() {
        return (String)sObj;
    }
}

@isTest
public class TestCustomComponentController {
    public static testmethod void doTest () {
        Test.setCurrentPage(Page.ThePage);
        CustomComponentController cont = new CustomComponentController();
        System.assertEquals(cont.getRecType(), 'Lead');
    }
}

Implemented like that, input into a page I can see that {!recType} evaluates to lead, but when I run the test getRecType() returns null.

I would really like a reference to how all of these things are architected, because I am sure to come across other issues like this in the future, but I can't find anything except simple examples.

1

1 Answer 1

4

Testing a controller is independent of testing the component. That is, you test the controller by simulating the inputs to the controller's properties as if VF passed them to the controller . Thus, your testmethods need to set the controller properties.

So, your testmethod should look like

@isTest
public class TestCustomComponentController {
    public static testmethod void doTest () {
        Test.setCurrentPage(Page.ThePage);  // not really needed to test the component itself
        CustomComponentController cont = new CustomComponentController();
        cont.sObj = new Lead();   // simulate the assignTo operation on the apex:attribute
        System.assertEquals(cont.getRecType(), 'Lead');
    }
}

You don't need to put the component on a testpage to test the controller

BTW -- I'm a bit confused by the method getRecType() - it is returning the sObj as a string. SFDC recordTypes are a concept altogether different from sObjects so you might want to change your methodname

5
  • A lot of my code is pretty rough. I was unable to get consistent behavior treating it as anything but a string :(
    – Alex H
    Commented Oct 15, 2014 at 17:12
  • yes - but the method should be named something like getSobjType()
    – cropredy
    Commented Oct 16, 2014 at 19:37
  • What if you are assigning the attributes in the constructor of the controller? How do you test that? Commented Sep 1, 2017 at 14:54
  • @PePeQuiCoSE - by definition, the assignTo attributes are set after the component's constructor is executed. If you are defaulting their values in the constructor, then merely instantiate the controller and then do asserts on the properties set by the constructor. If this isn't making sense to you, post a new question with your code
    – cropredy
    Commented Sep 1, 2017 at 18:42
  • Refactoring a class had a string as an attribute that needed to be converted to an enum and I was trying to do it in the constructor. Ended up doing it in an outside method, good to know it was not going to work anyways. Thanks! Commented Sep 3, 2017 at 1:05

You must log in to answer this question.

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