You need to sign in to do that
Don't have an account?
Pete Watson 5
Test Class for Custom Controller Adding Multiple Lines
Hi all,
Many thanks in advance for reading.
Im struggling to create a test class for this custom controller. i'm only getting 12% coverage so im clearly doing something fundamentally wrong but with limited experience with custom controllers i'd really appreciate any help?
Again, much appreciation!
CONTROLLER
CURRENT TEST CLASS
VISUALFORCE PAGE
Many thanks in advance for reading.
Im struggling to create a test class for this custom controller. i'm only getting 12% coverage so im clearly doing something fundamentally wrong but with limited experience with custom controllers i'd really appreciate any help?
Again, much appreciation!
CONTROLLER
public class AddMultipleLinesQuoteController { Opportunity opportunity; ABS_Product__c ABSProduct; Quote_Custom__C quote; Quote_Line__c qLine; public Integer rowIndex {get;set;} public Opportunity getOpportunity() { if(Opportunity == null) Opportunity = [select id, name, AccountId,ownerID from Opportunity where id = :ApexPages.currentPage().getParameters().get('id')]; return Opportunity; } public Quote_Custom__C getquote() { if(quote == null) quote = new Quote_Custom__C(); return quote; } public Quote_Line__c getqLine() { if(qLine == null) qLine = [select id,name,Discount__c,ABS_Product__c,Denomination__c, Line_Total__c,Quantity__c,Quote__c from Quote_Line__c]; return qLine; } public ABS_Product__c getABSProduct() { if(ABSProduct == null) ABSProduct = [select id, name from ABS_Product__c]; return ABSProduct; } Quote_Line__c line = new Quote_Line__c(); public list<Quote_Line__c> listlines{ get; set; } public AddMultipleLinesQuoteController() { listlines = new list<Quote_Line__c>(); listlines.add(line); } Public void addline() { Quote_Line__c l = new Quote_Line__c(); listlines.add(l); } public PageReference deleteRow(){ rowIndex = Integer.valueOf(ApexPages.currentPage().getParameters().get('rowIndex')); listlines.remove(rowIndex); return null; } public PageReference saveline() { if (line.ABS_Product__c == null || line.Denomination__c == null || line.Quantity__c == null || line.Discount__c == null) { ApexPages.addmessage(new ApexPages.message(ApexPages.severity.ERROR,'Please ensure all quote lines are populated')); return null; } if ( (Quote.Delivery_Address_Line_1__c != NULL || Quote.Delivery_Address_City__c != NULL || Quote.Delivery_Address_Country__c != NULL || Quote.Delivery_Address_Post_Code__c != NULL) && (Quote.Delivery_Address_Line_1__c == NULL || Quote.Delivery_Address_City__c == NULL || Quote.Delivery_Address_Country__c == NULL || Quote.Delivery_Address_Post_Code__c == NULL)) { ApexPages.addmessage(new ApexPages.message(ApexPages.severity.ERROR,'If you are entering a physical delivery address please ensure all fields are completed')); return null; } if ( (Quote.Delivery_Address_Line_1__c == NULL && Quote.Delivery_Address_City__c == NULL && Quote.Delivery_Address_Country__c == NULL && Quote.Delivery_Address_Post_Code__c == NULL) && (Quote.Digital_Delivery_Name__c == null && Quote.Digital_Delivery_Email__c == null)) { ApexPages.addmessage(new ApexPages.message(ApexPages.severity.ERROR,'Please enter either a physical delivery address or a digital delivery address')); return null; } if ( (Quote.Digital_Delivery_Name__c != null || Quote.Digital_Delivery_Email__c != null) && (Quote.Digital_Delivery_Name__c == null || Quote.Digital_Delivery_Email__c == null)) { ApexPages.addmessage(new ApexPages.message(ApexPages.severity.ERROR,'If you are entering a digital delivery address please ensure both fields are completed')); return null; } if(line.Quote__c == null){ quote.Opportunity__c = Opportunity.id; insert quote; List<Quote_Line__c> con = new List<Quote_Line__c>(); for(Quote_Line__c c : listlines){ c.quote__c = quote.id; con.add(c); } insert con; system.debug('listLines inserted'); } PageReference quotePage = new ApexPages.StandardController(new Quote_Custom__c(id=quote.Id)).view(); quotePage.setRedirect(true); return quotePage; } }
CURRENT TEST CLASS
@IsTest public class MultipleLinesQuoteControllerTest { private static testmethod void testMultipleLinesQuoteController(){ Account acc = new Account(); acc.Phone = '01516531700'; acc.name = 'testAcc'; acc.type = 'Customer'; acc.website = 'www.parkgroup.com'; acc.BillingCity = 'Park House'; acc.BillingCountry = 'Park House'; acc.BillingPostalCode = 'NW10 6AJ'; acc.BillingStreet = 'Street'; acc.Corp_Business_Type__c = 'Staff Rewards- Corporate'; acc.Discount__c ='0%'; acc.Industry = 'Finance'; acc.Lead_Source__c='existing'; insert acc; Opportunity opp = new Opportunity(); opp.name = 'test opp'; opp.AccountId = acc.id; opp.amount = decimal.valueOf(1000); opp.First_Order_Value__c = decimal.valueOf(1000); opp.closeDate = date.today(); opp.type = 'New Business'; opp.StageName = 'Qualified'; insert opp; AddMultipleLinesQuoteController controller = new AddMultipleLinesQuoteController(); Opportunity o = controller.getOpportunity(); PageReference pageRef = Page.quoteinput; pageRef.getParameters().put('id', String.valueOf(opp.Id)); Test.setCurrentPage(pageRef); ABS_Product__c prod = controller.getABSProduct(); prod.name = 'Love2shop Gift Card'; Quote_Custom__c qu = controller.getQuote(); qu.Delivery_Address_Line_1__c = 'street'; qu.Delivery_Address_City__c = 'city'; qu.Delivery_Address_Country__c ='country'; qu.Delivery_Address_Post_Code__c = 'l1 1aa'; qu.Quote_PO_Reference__c = 'po'; qu.Quote_Detail_Notes__c = 'details'; qu.Opportunity__c = opp.id; Quote_Line__c quLine = controller.getqLine(); quLine.Discount__c = decimal.valueOf(1); quLine.ABS_Product__c = prod.id; quLine.Denomination__c = decimal.valueOf(10); quLine.Quantity__c = decimal.valueOf(1); quLine.Quote__c = qu.id; Quote_Line__c quLine2 = controller.getqLine(); quLine2.Discount__c = decimal.valueOf(1); quLine2.ABS_Product__c = prod.id; quLine2.Denomination__c = decimal.valueOf(10); quLine2.Quantity__c = decimal.valueOf(1); quLine2.Quote__c = qu.id; controller.addline(); controller.deleteRow(); controller.saveline(); } }
VISUALFORCE PAGE
<apex:page Controller="AddMultipleLinesQuoteController" lightningStylesheets="true" sidebar="false" > <head> <style type="text/css" media="print"> .title { font-size: 12px; font-weight: bold; color: #5670ab; } </style> </head> <apex:form > <apex:pageBlock id="pb"> <apex:pageMessages ></apex:pageMessages> <apex:pageBlockSection title="Quote Details"> <apex:inputField value="{!opportunity.Name}"/> <apex:inputField value="{!Quote.Quote_PO_Reference__c}" required="true"/> </apex:pageBlockSection> <apex:pageBlockSection title="Delivery Details" columns="2"> <apex:outputtext style="font-size: 14px;font-weight: bold;color: #5670ab;" value="Address for physical delivery:"/><br/> <apex:inputField value="{!Quote.Delivery_Address_Line_1__c}"/><br/> <apex:inputField value="{!Quote.Delivery_Address_City__c}" /><br/> <apex:inputField value="{!Quote.Delivery_Address_Post_Code__c}"/><br/> <apex:inputField value="{!Quote.Delivery_Address_Country__c}"/><br/> <apex:outputtext style="font-size: 14px;font-weight: bold;color: #5670ab;" value="Address for digital delivery:"/><br/> <apex:inputField value="{!Quote.Digital_Delivery_Name__c}"/> <apex:inputField value="{!Quote.Digital_Delivery_Email__c}"/> </apex:pageBlockSection> <br/> <apex:outputtext style="font-size: 14px;font-weight: bold;color: #5670ab; text-align: center;" value="Please detail the quote lines below, totals will be generated on the quote pdf:"/><br/> <br/> <apex:variable var="rowNumber" value="{!0}"/> <apex:pageBlockTable value="{!listlines}" var="l"> <apex:param value="{!rowNumber+1}"/> <apex:column headerValue="Item"> <apex:inputField value="{!l.ABS_Product__c}" /> </apex:column> <apex:column headerValue="Denomination/Value" style="width: 40%;"> <apex:inputField value="{!l.Denomination__c}" /> </apex:column> <apex:column headerValue="Quantity" style="width: 40%;"> <apex:inputField value="{!l.Quantity__c}" /> </apex:column> <apex:column headerValue="Discount" style="width: 40%;"> <apex:inputField value="{!l.Discount__c}" /> </apex:column> <apex:column > <apex:commandButton value="X" action="{!deleteRow}" reRender="pb" style="font-weight:bold; color: red;"> <apex:param name="rowIndex" value="{!rowNumber}"/> </apex:commandButton> <apex:variable var="rowNumber" value="{!rowNumber+1}"/> </apex:column> </apex:pageBlockTable> <apex:pageBlockSection title="Details/Notes" columns="1" > <apex:inputField label="" style="width: 100%; align: center;" value="{!quote.Quote_Detail_Notes__c}"/> </apex:pageBlockSection> <apex:pageBlockButtons location="Bottom" > <apex:commandButton value="Add New Row" action="{!addline}"/> <apex:commandButton value="Generate Quote" action="{!saveline}"/> </apex:pageBlockButtons> <apex:pageMessages ></apex:pageMessages> </apex:pageBlock> </apex:form> </apex:page>
Hello again Pete, sorry for the long wait for a reply!
With that said, to test these scenarios, you would have to call the controller.saveline() three times,Since you would like to have either a digital address or a physical address, I would first add a checkbox to the VF-page, where the user chose which one they would like to have, setting a variable to true or false and only showing inputfields for that type of address.
This way you could do an if/else to see if there are any missing information, to make less of expressions in IF statements.
(Option for if you don't want to add this extra checkbox further down in my answer)
once with digitalAddress being set to true and no information in one or all of the fields: Digital_Delivery_Name__c, Digital_Delivery_Email__c.
Once with digitalAddress being set to false and no information in one or all of the fields:
Delivery_Address_Line_1__c , Delivery_Address_City__c , Delivery_Address_Country__c, Delivery_Address_Post_Code__c .
If you do not go with the solution of adding a Boolean-variable for digitalAddress check, you would just have to do the same as above, where you just leave one of the fields that you are checking unfilled each time you call the saveline()-method.
Remember that you might have to set the value for the variables in your apex class from the testclass by using the "controller.variablename" way, where variablename are one of the variables that you have in the testclass that is being used in the saveline()-method.
I hope that you don't get lost in what I've written above! :)
All Answers
Hello Pete,
Are there any errors in the debug log when you run the test-class?
Which rows aren't showing as tested in the apex class?
and
thanks
Thanks, can you provide a copy of the log please, it might help me find a reason for this behaviour.
HERE (https://parkgroup.my.salesforce.com/sfc/p/0Y000000aP9i/a/1v0000007Z4X/0Yc_Asyl1tTUHGEA1JfqxZvEfoT1IdQEOiZH1HnDPv0)
From what I can see, the testmethod called: "testMultipleLinesQuoteController1" gets an error when it tries to use the
"AddMultipleLinesQuoteController.getOpportunity"-method
This could be because you try to use the method before you have set the Id to the Opp id you wanted, causing the "id" variable to be undefined:
Instead you'd want to set the parameter before you call the getOpportunity-method.
Try this!
NEW TEST CLASS
New Log (https://parkgroup.my.salesforce.com/sfc/p/0Y000000aP9i/a/1v0000007Z5L/o3o5Ak82JGLCW5xFYZEbAwV5.cVKD1k_7b7_1T0cLl0)
Many thanks!
In your testclass, you aren't creating Quote_Line__c records and inserting them, therefore it won't find any records with your
"AddMultipleLinesQuoteController.getqLine()"
Maybe you could add this to the "getqLine()"-method:
In the situations that the list is empty, then it would send a new Quote_Line__c record.
Also, this query would get ALL records of the Quote_Line__c object.
Maybe you should add 'LIMIT 1' to the end of the query to set the max amount of records that could be returned.
But if this method is used to just create a new Quote_Line__c record, I would add a parameter to the method where you send in the Quote record that the Quote Line should be related to:
Ok, so since the method tries to fetch the 'rowIndex' parameter from the page, you should set the 'rowIndex' variable to the currentPage before calling the deleteRow()-method.
Something like this would perhaps work.Hello again Pete, sorry for the long wait for a reply!
With that said, to test these scenarios, you would have to call the controller.saveline() three times,Since you would like to have either a digital address or a physical address, I would first add a checkbox to the VF-page, where the user chose which one they would like to have, setting a variable to true or false and only showing inputfields for that type of address.
This way you could do an if/else to see if there are any missing information, to make less of expressions in IF statements.
(Option for if you don't want to add this extra checkbox further down in my answer)
once with digitalAddress being set to true and no information in one or all of the fields: Digital_Delivery_Name__c, Digital_Delivery_Email__c.
Once with digitalAddress being set to false and no information in one or all of the fields:
Delivery_Address_Line_1__c , Delivery_Address_City__c , Delivery_Address_Country__c, Delivery_Address_Post_Code__c .
If you do not go with the solution of adding a Boolean-variable for digitalAddress check, you would just have to do the same as above, where you just leave one of the fields that you are checking unfilled each time you call the saveline()-method.
Remember that you might have to set the value for the variables in your apex class from the testclass by using the "controller.variablename" way, where variablename are one of the variables that you have in the testclass that is being used in the saveline()-method.
I hope that you don't get lost in what I've written above! :)