You need to sign in to do that
Don't have an account?
Test Method for Custom Controller
Hi,
I am fairly new to Apex development and programming in general. My particular issue is that I am having trouble creating a test method for a custom controller. I have a VF page with a simple form for submitting cases, and a custom controller to handle it. I've deployed the VF page and controller to my developement org and everything works properly. Now I want to deploy it to production but need test coverage.
I have read through the Apex Developer's Guide and countless forum postings on developing test methods but I am still stumped.
Below is the VF page, Custom Controller class, and my current (inadequate) test method.
VF Page: simple case submit form
<apex:page controller="SubmitCaseController"> <h1>Submit New Case</h1> <apex:form > <apex:pageMessages /> <table> <tr> <th>Your Name:</th> <td><apex:inputText value="{!c.SuppliedName}"/></td> </tr> <tr> <th>Your Email:</th> <td><apex:inputText value="{!c.SuppliedEmail}"/></td> </tr> <tr> <th>Your Account Number:</th> <td><apex:inputText required="true" value="{!acctNum}"/></td> </tr> <tr> <th>Title:</th> <td><apex:inputText required="true" value="{!c.Subject}"/></td> </tr> <tr> <th>Your Problem:</th> <td><apex:inputTextArea required="true" rows="5" value="{!c.Description}"/></td> </tr> <tr> <td><apex:commandButton value="Submit Case" action="{!submitCase}"/></td> </tr> </table> </apex:form></apex:page>
Custom Controller: The general functionality is to use the acctnum field to match an existing account. Then, find the appropriate contact by matching the account and email address. Then insert the case.
public with sharing class SubmitCaseController { public Case c { get; set; } public String acctNum { get; set; } public SubmitCaseController() { c = new Case(); } public PageReference submitCase() { List<Account> accts = [SELECT Id FROM Account WHERE AccountNumber = :acctNum]; if (accts.size() != 1) { ApexPages.Message msg = new ApexPages.Message(ApexPages.Severity.FATAL, 'Invalid account number'); ApexPages.addMessage(msg); return null; } else { try { c.AccountId = accts.get(0).Id; // now look for an associated contact with the same email Contact cnt = [SELECT Id FROM Contact WHERE AccountId = :c.AccountId AND Email = :c.SuppliedEmail LIMIT 1]; if (cnt != null) c.ContactId = cnt.Id; // Specify DML options to ensure the assignment rules are executed Database.DMLOptions dmlOpts = new Database.DMLOptions(); dmlOpts.assignmentRuleHeader.useDefaultRule = true; c.setOptions(dmlOpts); // Insert the case INSERT c; return new PageReference('/thanks'); } catch (Exception e) { ApexPages.addMessages(e); return null; } } }}
My current test method:
@isTestprivate class SubmitCaseControllerTests { public static testMethod void testSubmitCaseController() {PageReference pageRef = Page.PortalCaseSubmit; Test.setCurrentPage(pageRef); Account testaccount = new Account(name = 'Acme', AccountNumber='123456'); insert testaccount; Contact testcontact = new Contact(firstname='joe', lastname='smith', email='joe@smith.com'); insert testcontact; Case c; c.SuppliedName='Joe Smith'; c.SuppliedEmail='joe@smith.com'; c.Subject = 'Test'; c.Description = 'This is a test.'; String acctnum = '123456'; SubmitCaseController controller = new SubmitCaseController(); controller.submitcase(); Case cases = [Select ID, subject, description from Case Where account.id = :testaccount.id]; System.assertequals(cases.description, c.description); } }
My logic is to instantiate an account and contact and insert them into the database. Then, mimic the process of someone completing the form and submitting it. I could test both positive and negative results this way. However, I am stumped as to how to populate the form fields and submit the form using Apex. Any help would be appreciated.
Thanks,
Clint
Ahhh - Apex doesn't have deep equality checking outside of sObjects - in this case, the object references are compared and found to be different.
I usually just check the URL aspects of the page are the same:
System.assertEquals(expectedPr.getUrl(), controller.method.getUrl());
All Answers
I'm reposting the above code since it did not show up correctly.
VF Page:
<apex:page controller="SubmitCaseController"><h1>Submit New Case</h1> <apex:form ><apex:pageMessages /><table><tr> <th>Your Name:</th> <td><apex:inputText value="{!c.SuppliedName}"/></td></tr><tr> <th>Your Email:</th> <td><apex:inputText value="{!c.SuppliedEmail}"/></td></tr><tr> <th>Your Account Number:</th> <td><apex:inputText required="true" value="{!acctNum}"/></td></tr><tr> <th>Title:</th> <td><apex:inputText required="true" value="{!c.Subject}"/></td></tr><tr> <th>Your Problem:</th> <td><apex:inputTextArea required="true" rows="5" value="{!c.Description}"/></td></tr><tr> <td><apex:commandButton value="Submit Case" action="{!submitCase}"/></td></tr></table></apex:form></apex:page>
Custom Controller:
public with sharing class SubmitCaseController { public Case c { get; set; } public String acctNum { get; set; } public SubmitCaseController() { c = new Case();} public PageReference submitCase() { List<Account> accts = [SELECT Id FROM Account WHERE AccountNumber = :acctNum]; if (accts.size() != 1) { ApexPages.Message msg = new ApexPages.Message(ApexPages.Severity.FATAL, 'Invalid account number'); ApexPages.addMessage(msg); return null; } else { try { c.AccountId = accts.get(0).Id; // now look for an associated contact with the same email Contact cnt = [SELECT Id FROM Contact WHERE AccountId = :c.AccountId AND Email = :c.SuppliedEmail LIMIT 1]; if (cnt != null) c.ContactId = cnt.Id; // Specify DML options to ensure the assignment rules are executed Database.DMLOptions dmlOpts = new Database.DMLOptions(); dmlOpts.assignmentRuleHeader.useDefaultRule = true; c.setOptions(dmlOpts); // Insert the case INSERT c; return new PageReference('/thanks');} catch (Exception e) {ApexPages.addMessages(e); return null; } } }}
My current test method: (0% coverage)
@isTest private class SubmitCaseControllerTests { public static testMethod void testSubmitCaseController() { PageReference pageRef = Page.PortalCaseSubmit; Test.setCurrentPage(pageRef); Account testaccount = new Account(name = 'Acme', AccountNumber='123456'); insert testaccount; Contact testcontact = new Contact(firstname='joe', lastname='smith', email='joe@smith.com'); insert testcontact; Case c; c.SuppliedName='Joe Smith'; c.SuppliedEmail='joe@smith.com'; c.Subject = 'Test'; c.Description = 'This is a test.'; String acctnum = '123456'; SubmitCaseController controller = new SubmitCaseController(); controller.submitcase(); Case cases = [Select ID, subject, description from Case Where account.id = :testaccount.id]; System.assertequals(cases.description, c.description); }}
Thanks again!
Ah the joys of pasting code - I find I have to edit the message and manually insert the newlines!
With regard to testing, you wouldn't fill out the form and submit it back. Rather you'd set the values of the various properties that back the form, invoke the action method that the submit button is bound to and check that the resulting page reference matches the expected result.
From the look of your code, I'd guess you need something like the following:
// insert account test data here
SubmitCaseController controller=new SubmitCaseController();
controller.acctNum=testAcctNum;
PageReference expectedPR=new PageReference('/thanks');
System.assertEquals(expectedPR, controller.submitCase());
where testAcctNum is the account number from some test data you have inserted.
Bob,
Thank you for your feedback. That helped out alot. I updated the test method to include your suggestion and it seems like it should have worked. However, I received the following line which shows that the expected result == the actual result but still says that the assertion failed, and the overall test failed with 0% coverage. I'm not sure how that could happen...
System.Exception: Assertion Failed: Expected: System.PageReference[/apex/tfgff__thanks], Actual: System.PageReference[/apex/tfgff__thanks]
(The tfgff is our namespace prefix)
Any thoughts?
Thanks again!
Clint
Ahhh - Apex doesn't have deep equality checking outside of sObjects - in this case, the object references are compared and found to be different.
I usually just check the URL aspects of the page are the same:
System.assertEquals(expectedPr.getUrl(), controller.method.getUrl());
Awesome, that worked great.
Thanks so much! I really appreciate your help.
Clint
I also trying to create a test controller for this code and get the following error:
Save error: Variable does not exist: method submitcasecontrollertest.cls
I used the following code as you instructed.
SubmitCaseController controller=new SubmitCaseController(); controller.acctNum='123456'; PageReference expectedPR=new PageReference('/thanks'); System.assertEquals(expectedPr.getUrl(), controller.method.getUrl());