+ Start a Discussion
Thomas FullerThomas Fuller 

Apex Test Code - Issue with Building a Test Class for Apex Extension

Hey everybody,

I am currently in the process of deploying my first larger application that I have developed to my production org. However, I am running into issues with writing functioning apex test code. I’m only really familiar with basics of test classes, and I was hoping that a more experienced developer could lend a hand in helping me build a sleek, quality test class for a controller extension for a custom VF page.

The following code is used for one part of the application. This part includes a custom VF page, which displays a list of all child “ML_List__c” within the “ML_List_Container__c” parent object, and an extension, which attempts to create a string of emails and ids to be passed into an apex plugin later on. So far with the provided test code, I get 24% code coverage. However, I still have got a “No rows for assignment error”, and I’m kind of lost for a solution.

Code Samples:

Custom VF:
<apex:page StandardController="ML_List_Container__c" extensions="mLContainerExtension">
...
</apex:page>

* The symbol "..." refers to code deemed "irrelevant" that was cut out to decrease the size of the post.

Controller Extension:
public with sharing class mLContainerExtension {
	
	public final List<ML_List__c> marketingList;
	public final ML_List_Container__c currentRecord;
	public String emailContainerString {get;set;}
	public String idContainerString {get;set;}
	
    public mLContainerExtension(ApexPages.StandardController stdController) {
        marketingList = [
            SELECT Name, Id, Contact__r.Email, Contact__r.Id, Lead__r.Email, Lead__r.Id
            FROM ML_List__c
            WHERE ML_List_Container__c = :ApexPages.currentPage().getParameters().get('Id')
        ];
        currentRecord = [
        	SELECT Name, Id, description__c, CreatedBy.Name, CreatedDate
            FROM ML_List_Container__c
            WHERE Id = :ApexPages.currentPage().getParameters().get('Id')
            LIMIT 1
        ];
        emailContainerString = '';
        idContainerString = '';
        for (ML_List__c mLList : marketingList) {
        	String emailAdd = '';
        	String idAdd = '';
        	if (mLList.Lead__r.Email == null){
        		emailAdd = mLList.Contact__r.Email;
        	}
        	else {
        		emailAdd = mLList.Lead__r.Email;
        	}
        	if (mLList.Lead__r.Id == null){
        		idAdd = mLList.Contact__r.Id;
        	}
        	else {
        		idAdd = mLList.Lead__r.Id;
        	}
        	if (emailAdd != null) {
        		emailContainerString += emailAdd + ', ';
        	}
        	if (idAdd != null) {
        		idContainerString += idAdd + ', ';
        	}
        }
    }
    
    public List<ML_List__c> getMarketingList() {
        return marketingList;
    }
    
    public ML_List_Container__c getCurrentRecord() {
        return currentRecord;
    }

    public PageReference save() {
        update marketingList;
        return null;
    }
    
    public String getFinishPage() {
        return '/apex/ML_Container_Layout?id='+ currentRecord.Id + '&sfdc.override=1';
    }
}

Test Class (24% code coverage and contains "no rows for assignment" error):
@isTest
private class testMLContainerExtension {

    static testMethod void myUnitTest() {
        
                ML_List_Container__c mLLC = new ML_List_Container__c(Name = 'TestContainer');
		
		insert mLLC;

		ApexPages.StandardController sc = new ApexPages.standardController(mLLC);
		
		mLContainerExtension controller = new mLContainerExtension(sc);

    }

}

I will be very grateful for any ideas, suggestions, comments, or advice anyone may provide. Thank you for your time.

Thanks,
Thomas
James LoghryJames Loghry
You have a few different issues at hand here:
  1. The "No rows for assignment" error is likely due to you not setting the "Id" parameter in the Current Page.  You can either do this by calling ApexPages.currentPage().getParameters().put('Id',recordId) OR change your extension constructor to utilize the StandardController's "getId()" method.
  2. You're not creating any ML_List__c record, nor associating them with the parent ML_List_Container__c record.  (See the unit test example below)
  3. Furthermore, your code could improve by combining the two queries in your extensions constructor into one SOQL query using a subquery for the related records. See the example below for an idea on how you would accomplish this.
  4. You're not calling any methods other than the constructor.  I'd suggest creating a separate testmethod for each of your methods.  See an example below for how this looks for both the constructor and getFinishPage().
  5. You don't have any system asserts.  Technically you can get by with not having System asserts, however, this is a horrible idea.  YOu should always have many System asserts in your unit test for verifying your code is doing what it is expected to do.  Again, I've added some in to the getFinishPage() method for you.
  6. There are probably additional issues you're going to run into, but those are the main culprits you need to worry about if you're going to deploy this to production.
@isTest
private class testMLContainerExtension {
    static testMethod void myUnitTestConstructor() {
        ML_List_Container__c mLLC = new ML_List_Container__c(Name = 'TestContainer');
        List<ML_List__c> lists = new List<ML_List__c>();
        lists.add(new ML_List_Container__c(Name='TestList1',ML_List_Container__c=mLLc.Id));
        lists.add(new ML_List_Container__c(Name='TestList2',ML_List_Container__c=mLLc.Id));
        insert lists;

        ApexPages.StandardController sc = new ApexPages.standardController(mLLC);
        mLContainerExtension controller = new mLContainerExtension(sc);
        
    }

     static testMethod void myUnitTestGetFinishPage() {
        ML_List_Container__c mLLC = new ML_List_Container__c(Name = 'TestContainer');
        List<ML_List__c> lists = new List<ML_List__c>();
        lists.add(new ML_List_Container__c(Name='TestList1',ML_List_Container__c=mLLc.Id));
        lists.add(new ML_List_Container__c(Name='TestList2',ML_List_Container__c=mLLc.Id));
        insert lists;

        ApexPages.StandardController sc = new ApexPages.standardController(mLLC);
        mLContainerExtension controller = new mLContainerExtension(sc);
        Test.startTest();
        PageReference actual = controller.getFinishPage();
        System.assertEquals('Something',actual.getUrl());
    }
}




public mLContainerExtension(ApexPages.StandardController stdController) {

        currentRecord =
            [Select 
                Name
                ,Id
                ,Description__c
                ,CreatedBy.Name
                ,CreatedBy.Date
                ,Lead__r.Id
                ,(Select
                    Name
                    ,Id
                    ,Contact__r.Email
                    ,Contact__r.Id
                    ,Lead__r.Email
                    ,Lead__r.Id
                From
                    ML_Lists__r)
             From
                ML_List_Container__c
             Where
                 Id = :stdController.getId()];

        marketingList = currentRecord.ML_Lists__r;
        //Other logic goes below here
}