[SalesForce] Visualforce Controller Unit Test (VF page displays fullcalendar)

I've written a visualforce page (with the help of examples etc from the internet) to simply display an instance of fullcalendar.js.

There's no buttons etc, it simply loads when clicked from the home tab link/button in salesforce. When the VF page loads, it displays a specific user's events/activities for any user viewing the page. I've tweaked the fullcalendar.js code to display additional details when an event is hovered.

I'm confused as to how to test the controller. The controller basically only gathers the events. I have a test that calls the pageLoad() method – it passes but only covers 15%… I had a lot more in the test but removed code that didn't help the coverage to start over.

Can anyone help me to understand how to initiate the rest of the controller code in the test? Sorry for all of the code copied below – but I've been working on this for about a week and I've finally decided to reach out for HELP! I've not included the fullcalaendar script files at this time (saved as static resources). Please note that this VF page works exactly how I want it to, I just can't seem to test it properly…

Thanks in advance!

VF Page code:

 <apex:page controller="MiroCalendar_Controller02" action="{!pageLoad}">
<link href="{!$Resource.fullCalendarCSS}" rel="stylesheet" />
<link href="{!$Resource.fullCalendarPrintCSS}" rel="stylesheet" media="print" />    

<script src="{!$Resource.JqueryMinJS}"></script>
<script src="{!$Resource.JqueryUICustomMinJS}"></script>
<script src="{!$Resource.MomentMinJS}"></script>
<script src="{!$Resource.fullCalendarJS}"></script>


<script>

    //We need to wrap everything in a doc.ready function so that the code fires after the DOM is loaded
    $(document).ready(function() {
        //Call the fullCallendar method. You can replace the '#calendar' with the ID of the dom element where you want the calendar to go. 
        $('#calendar').fullCalendar({
            header: {
                left: 'prev,next today',
                center: 'title',
                right: 'month,agendaWeek,agendaDay'
            },
            editable: false,
            events:
            [
                //At run time, this APEX Repeat will render the array elements for the events array
                <apex:repeat value="{!events}" var="e">
                    {
                        title: "{!e.title}",
                        description: "{!e.description}",
                        createdBy: "{!e.createdBy}",
                        createdOn: "{!e.createdOnString}",
                        modifiedBy: "{!e.modifiedBy}",
                        modifiedOn: "{!e.modifiedOnString}",
                        start: '{!e.startString}',
                        end: '{!e.endString}',
                        url: '{!e.url}',
                        allDay: {!e.allDay},
                        className: '{!e.className}'
                    },
                </apex:repeat>
            ]
       });                
    });

</script>

<!--some styling. Modify this to fit your needs -->
<style>
    #cal-options {float:left;}
    #cal-legend { float:right;}
    #cal-legend ul {margin:0;padding:0;list-style:none;}
    #cal-legend ul li {margin:0;padding:5px;float:left;}
    #cal-legend ul li span {display:block; height:16px; width:16px; margin-right:4px; float:left; border-radius:4px;}
    #calendar {margin-top:20px;}
    #calendar a:hover {color:#fff !important;}

    .fc-event-inner {padding:3px;}
    .event-miro-corp {background:#aea5cd;border-color:#e93329;}
    .event-miro-bank {background:#c7b676;border-color:#e93329;}
    .event-miro-retail {background:#e93329;border-color:#e93329;}
    .event-miro-other {background:#a19f9b;border-color:#e93329;}
    .event-miro-error {background:#ffa500;border-color:#e93329;}
</style> 

<apex:sectionHeader title="Miro's Calendar"/>
<apex:outputPanel id="calPanel">
    <apex:form >
        <!--<div id="cal-options">
            <apex:commandButton value="{!IF(includeMyEvents,'Hide My Events','Show My Events')}" action="{!toggleMyEvents}"/>
        </div>-->
        <div id="cal-legend">
            <ul>
                <li><span class="event-miro-corp"></span>Corp Installs</li>
                <li><span class="event-miro-bank"></span>Bank Installs</li>
                <li><span class="event-miro-retail"></span>Retail Installs</li>
                <li><span class="event-miro-other"></span>Other</li>
                <!--<li><span class="event-miro-error"></span>Error</li>-->
            </ul>
            <div style="clear:both;"><!--fix floats--></div>
        </div>
        <div style="clear:both;"><!--fix floats--></div>
        <div id="calendar"></div>
    </apex:form>
</apex:outputPanel>

Controller:

public class MiroCalendar_Controller02 {
public list<calEvent> events {get;set;}   

//The calendar plugin is expecting dates is a certain format. We can use this string to get it formatted correctly
String dtFormat = 'EEE, d MMM yyyy HH:mm:ss z';
//constructor

public PageReference pageLoad() {
    events = new list<calEvent>();

    //Get my Events if we have selected the correct option
    for(Event evnt: [select Id, Subject, isAllDayEvent, Description, StartDateTime, EndDateTime, CreatedById, CreatedDate, LastModifiedById, LastModifiedDate from Event where OwnerID = :'005i0000000jxVsAAI' AND ActivityDate > LAST_MONTH]){
        DateTime startDT = evnt.StartDateTime;
        DateTime endDT = evnt.EndDateTime;
        DateTime createdOn = evnt.CreatedDate;
        DateTime modifiedOn = evnt.LastModifiedDate;
        String createdByName = '';
        String modifiedByName = '';
        String classType = '';
        calEvent miroEvent = new calEvent();                

        classType = 'event-miro-corp';

        miroEvent.title = evnt.Subject;
        miroEvent.allDay = evnt.isAllDayEvent;
        miroEvent.startString = startDT.format(dtFormat);
        miroEvent.endString = endDT.format(dtFormat);
        miroEvent.url = '/' + evnt.Id;
        miroEvent.className = classType;
        miroEvent.description = evnt.Description;
        miroEvent.createdBy = createdByName;
        miroEvent.createdOnString = createdOn.format(dtFormat);
        miroEvent.modifiedBy = modifiedByName;
        miroEvent.modifiedOnString = modifiedOn.format(dtFormat);
        events.add(miroEvent);
        }
    return null;
}    


//Class to hold calendar event data
public class calEvent{
    public String title {get;set;}
    public Boolean allDay {get;set;}
    public String startString {get;private set;}
    public String endString {get;private set;}
    public String url {get;set;}
    public String className {get;set;}
    public String description {get;set;}
    public String createdBy {get;set;}
    public String createdOnString {get;set;}
    public String modifiedBy {get;set;}
    public String modifiedOnString {get;set;}
}
}

TEST Controller:

@isTest
public class MiroCalendar_Controller02Tests {

public static testMethod void testMiroController02() {
    PageReference pageRef = Page.MiroCalendar;
    Test.setCurrentPage(pageRef);

    // Instantiate a new controller with all parameters in the page
    MiroCalendar_Controller02 testcontroller = new MiroCalendar_Controller02();
    testcontroller.pageLoad();

}
}

Best Answer

Unit tests are meant to exercise your code so that you can test what you would expect to happen in your code. When I'm writing unit tests, I go back to the functional requirements of my code and think about what logic it performs. How would I setup all of the context and data for my code to execute in the way I was expecting?

In your case, you are returning a list of events. As such, your unit test needs to create those events so they can be returned. The reason that you have big blocks of code not being exercised is because you aren't getting into the for loop of your test because there are no events in the database in the unit test context (isolated from the data in your instance). Create an event, which you'll need to hardcode to the specific owner you listed in your controller prior to all of the code that's currently in your test.

Here is a good article about best practices for writing unit tests: https://developer.salesforce.com/page/How_to_Write_Good_Unit_Tests

Related Topic