0

I Have this apex class which is called trough a button calling a visualforce page. How do I test my Pagereference in my testclass?

I do not have coverage from // Code we will invoke on page load.

Visualforce:

<apex:page standardController="Contract" extensions="ContractController" action="{!autoRun}">
</apex:page>

Controller

public class ContractController {

    // Constructor - this only really matters if the autoRun function doesn't work right
    private final Contract c;
    public ContractController(ApexPages.StandardController stdController) {
        this.c = (Contract)stdController.getRecord();
    }

    // Code we will invoke on page load.
    public PageReference autoRun() {

        String theId = ApexPages.currentPage().getParameters().get('id');

        if (theId == null) {
            // Display the Visualforce page's content if no Id is passed over
            return null;
        }

        // Execute code
        List<Contract> jaarcontracten = [SELECT id, ContractNumber, startdate FROM Contract WHERE Aantal_maanden__c = 12];
        for(Contract c: jaarcontracten ){
            c.startdate= Date.newInstance((c.startdate.year() + 1),1,1);
        }
        update jaarcontracten;

        // Redirect the user back to the original page
        PageReference pageRef = new PageReference('/' + theId);
        pageRef.setRedirect(true);
        return pageRef;

    }
}

Testclass:

@isTest
public class ContactControllerTest {
    @isTest  
    private static void testContactController() 
    { 
        Account acc = new account(name='acc');
        insert acc;

        Opportunity opp = New Opportunity(accountid = acc.id,closedate=date.today(),name='Test Opport',stagename='//STAGE NAME',Discount_Percent__c=0.2);
        insert opp;  

        list<contact> contacts=new list<contact>();                
        contacts.add(new contact(AccountId=acc.id,lastname='contact1LastNameA',firstname='Contact2FirstNameB',Lidnummer__c='9876543211',LeadSource='web',Splits__c=false));
        Insert Contacts;

        //Create the contract
        Contract con = new Contract(AccountId = opp.AccountId,ContractTerm = 12, StartDate = opp.CloseDate,OwnerExpirationNotice = '30');
        insert con;

        ApexPages.StandardController sc = new ApexPages.standardController(con);
        ContractController myPageCon = new ContractController(sc);

        PageReference pageRef = Page.VerlengingContract;
        pageRef.getParameters().put('id', String.valueOf(Contract.Id));

        Test.setCurrentPage(pageRef);
    }    
}
1
  • 2
    Verifying that your code works as you expect it to work is the most important part of unit testing. It’s also one of the things that Force.com developers commonly neglect. Unit tests that do not verify the results of the code aren’t true unit tests. They are commonly referred to as smoke tests, which aren’t nearly as effective or informative as true unit tests. - How to Write Good Unit Tests
    – Adrian Larson
    Commented Nov 13, 2017 at 13:30

2 Answers 2

2

Before you start working on coverage, you should spend some time understanding the chief goal of unit testing. Coverage is simply a side effect of well written tests, it should never be the primary goal.

As noted in How to Write Good Unit Tests (emphasis mine):

Verify the results are correct

Verifying that your code works as you expect it to work is the most important part of unit testing. It’s also one of the things that Force.com developers commonly neglect. Unit tests that do not verify the results of the code aren’t true unit tests. They are commonly referred to as smoke tests, which aren’t nearly as effective or informative as true unit tests.

A good way to tell if unit tests are properly verifying results is to look for liberal use of the System.assert() methods. If there aren’t any System.assert() method calls, then the tests aren’t verifying results properly. And, no, System.assert(true); doesn’t count.

Your test does not contain a single assertion, so you have not yet written a unit test.


Now, as for how to cover this particular code, you do what you would with any other code in your application, run the methods you want to test. Your testmethod never once calls autorun(). You will need to call your method more than once to hit each execution path. The basic structure of your method should look as follows:

static testmethod void testAutoRun_UseCase1()
{
    // set up data for a specific execution path

    Test.startTest();
        extension.autoRun();
    Test.stopTest();

    // verify behavior using assertions
}
static testmethod void testAutoRun_UseCase2()
{
    // set up data for a specific execution path

    Test.startTest();
        extension.autoRun();
    Test.stopTest();

    // verify behavior using assertions
}

You obviously have a few different execution paths:

  • Your Id value is null
  • Your Id value is populated and the update call succeeds
  • Your Id value is populated and the update call fails

Note how my pseudocode test above calls the class instance extension, not controller. Please take a moment to read Difference between controller and extensions and understand what sort of class definition you are writing. There are a couple other things you could improve about your class, specifically you should use the controller.getId method rather than the case-sensitive getParameters() approach.

public with sharing class MyExtension
{
    final Id recordId;
    final Contract record;
    public MyExtension(ApexPages.StandardController controller)
    {
        // you are accepting a controller as a parameter
        // this class is actually an EXTENSION

        recordId = controller.getId();
        record = (Contract)controller.getRecord();
    }
    public PageReference myMethod()
    {
        if (recordId == null)
        {
            // you should really add an error message to the page here
            return null;
        }

        // query related record and set some fields
        try
        {
            update relatedRecord;
        }
        catch (DmlException dmx)
        {
            // you will greatly improve the user experience
            // if you add some basic error handling
            ApexPages.addMessages(dmx);
            return null;
        }

        return somePageReference;
    }
}

One final note, it is much better practice to construct the view using the StandardController. The end of your method should simply read:

return new ApexPages.StandardController(relatedRecord).view();

You also don't need to call setRedirect(true) since that is the default value.

0
1

You have to actually call the method, as you would any other method you're testing. This is because you're not actually "calling" the page, so it doesn't do any work for you automatically. Here's how you'd call it:

    PageReference ref = myPageCon.autoRun();
    System.assert(ref.getUrl().contains(con.Id));

Note that you have additional logic problems in your code, so I would expect the above assertion to fail. Once you fix your code, the unit test should pass.

You must log in to answer this question.

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