function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
Pete Watson 5Pete 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
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>

​​​​​​​
 
Best Answer chosen by Pete Watson 5
Daniel AhlDaniel Ahl

Hello again Pete, sorry for the long wait for a reply!

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)
 

if(digitalAddress){ // digitalAddress = true
  if (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; 
  }
} else { // digitalAddress = false
   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){ 
        ApexPages.addmessage(new ApexPages.message(ApexPages.severity.ERROR,
        'If you are entering a physical delivery address please ensure all fields are completed')); return null; 
   } 
}


With that said, to test these scenarios, you would have to call the controller.saveline() three times,
once with digitalAddress being set to true and no information in one or all of the fields: Digital_Delivery_Name__cDigital_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 .
 
controller.digitalAddress = false;
controller.quote = qu; // To set the value of the variable Quote_Custom__C  quote;
controller.saveline(); // Here we already have all the fields we need filled out already, so no errors should be triggered.

// Then we have to reset the qu variables fields.
qu.Delivery_Address_Line_1__c = null;
qu.Delivery_Address_City__c = null;
qu.Delivery_Address_Country__c = null;
qu.Delivery_Address_Post_Code__c = null;
controller.quote = qu;
controller.saveline(); //Should cause error to be triggered.

// Set the digitalAddress to true
controller.digitalAdress = true;
controller.saveline(); //Should cause error to be triggered.


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

Daniel AhlDaniel Ahl

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?

Pete Watson 5Pete Watson 5
hi @Daniel, im getting a system query exception which iim unsure why to be honest and the code coverage is only covering the below blocks: 
 
public Opportunity getOpportunity() {
        if(Opportunity == null) 
            Opportunity = [select id, name, AccountId,ownerID from Opportunity 
                           where id = :ApexPages.currentPage().getParameters().get('id')];

and
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);

thanks 
​​​​​​​
Daniel AhlDaniel Ahl

Thanks, can you provide a copy of the log please, it might help me find a reason for this behaviour.

Daniel AhlDaniel Ahl

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:

Opportunity o = controller.getOpportunity();
PageReference pageRef = Page.quoteinput; 
pageRef.getParameters().put('id', String.valueOf(opp.Id));
Test.setCurrentPage(pageRef);
 

Instead you'd want to set the parameter before you call the getOpportunity-method.

PageReference pageRef = Page.quoteinput; 
pageRef.getParameters().put('id', String.valueOf(opp.Id));
Test.setCurrentPage(pageRef);
Opportunity o = controller.getOpportunity();

Try this!

Pete Watson 5Pete Watson 5
thats sorted that error thank you, up to 22% coverage now lol. 

NEW TEST CLASS
 
@IsTest
public class MultipleLinesQuoteControllerTest {
    
    private static testmethod void testMultipleLinesQuoteController1(){

        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;
        
        ABS_Product__c prod = new ABS_Product__c();
        	prod.name = 'Love2shop Gift Card';
        insert prod;

        AddMultipleLinesQuoteController controller = new AddMultipleLinesQuoteController(); 
        
        PageReference pageRef = Page.quoteinput; 
		pageRef.getParameters().put('id', String.valueOf(opp.Id));
		Test.setCurrentPage(pageRef);
		Opportunity o = controller.getOpportunity();
                
        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;
        
        Quote_Line__c quLine3 = controller.getqLine();
        	quLine3.Discount__c = decimal.valueOf(1);
            quLine3.ABS_Product__c = null;
            quLine3.Denomination__c = decimal.valueOf(10);
            quLine3.Quantity__c = decimal.valueOf(1);
            quLine3.Quote__c = qu.id;
        
        
        controller.addline();
        controller.deleteRow();
        controller.saveline();
        
        
    }
}

New Log (https://parkgroup.my.salesforce.com/sfc/p/0Y000000aP9i/a/1v0000007Z5L/o3o5Ak82JGLCW5xFYZEbAwV5.cVKD1k_7b7_1T0cLl0)

Many thanks! 
Daniel AhlDaniel Ahl

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:
 

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];
            if(qLine.size() <= 0 || qLine = null){
                qLine = new Quoute_Line__c();
            }
        return qLine;
    }

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:
 

public Quote_Line__c getqLine(String QuoteId) {
        return new Quote_Line__c(Quote__c = QuoteId);
        /*
        Or:
        return new Quote_Line__c(Quote_Custom__c = QuoteId); 
        Since it looks like the Quote object isn't Quote__c but rather Quote_Custom__c
        */
    }
Pete Watson 5Pete Watson 5
thanks, no more errors and coverage increased to 33%, now just need coverage on the addmessage blocks and the deleteRow() ? thanks!! 
Daniel AhlDaniel Ahl

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.

PageReference pageRef = Page.quoteinput; 
pageRef.getParameters().put('rowIndex', 0); 
Test.setCurrentPage(pageRef);
controller.deleteRow();
Something like this would perhaps work.
Pete Watson 5Pete Watson 5
Thank you VERY much for all your help today! could i ask one last question... im struggling still to get the addmessages blocks to be covered - could you provide a sample for one of these blocks and i'll figure out the others from there? Thanks again! 
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;
Daniel AhlDaniel Ahl

Hello again Pete, sorry for the long wait for a reply!

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)
 

if(digitalAddress){ // digitalAddress = true
  if (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; 
  }
} else { // digitalAddress = false
   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){ 
        ApexPages.addmessage(new ApexPages.message(ApexPages.severity.ERROR,
        'If you are entering a physical delivery address please ensure all fields are completed')); return null; 
   } 
}


With that said, to test these scenarios, you would have to call the controller.saveline() three times,
once with digitalAddress being set to true and no information in one or all of the fields: Digital_Delivery_Name__cDigital_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 .
 
controller.digitalAddress = false;
controller.quote = qu; // To set the value of the variable Quote_Custom__C  quote;
controller.saveline(); // Here we already have all the fields we need filled out already, so no errors should be triggered.

// Then we have to reset the qu variables fields.
qu.Delivery_Address_Line_1__c = null;
qu.Delivery_Address_City__c = null;
qu.Delivery_Address_Country__c = null;
qu.Delivery_Address_Post_Code__c = null;
controller.quote = qu;
controller.saveline(); //Should cause error to be triggered.

// Set the digitalAddress to true
controller.digitalAdress = true;
controller.saveline(); //Should cause error to be triggered.


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! :)

This was selected as the best answer
Pete Watson 5Pete Watson 5
thanks so much for all your help. its not 100% coverage but im on 80% now and thats good enough to deploy (fully confident from manual testing in its behaviour). Wouldn't have got this far without your help... much appreciated!