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
ckellieckellie 

Test Code coverage 44% - List gas no roes for assignment to object

In this test code, how do I assign rows to the object? Here is the error?

 

	System.QueryException: List has no rows for assignment to SObject	

Class.CloneOpportunityLineItems.CloneOpportunityLineItems: line 51, column 28 

Class.TestCloneOpportunityLineItems.basicSaveTest: line 31, column 32 External entry point

 

Test Code:

@IsTest private class TestCloneOpportunityLineItems{

    /* This is a basic test which simulates the primary positive case for the 
       save method in the quoteExt class. */
    public static testmethod void basicSaveTest() {

        /* Create an account */
        Account a = new Account();
        a.name    = 'TEST';
        Database.insert(a);

        /* Get a valid stage name */
        OpportunityStage stage = [select MasterLabel from OpportunityStage limit 1];

        /* Setup a basic opportunity */
        Opportunity o  = new Opportunity();
        o.Name         = 'TEST';
        o.AccountId    = a.id;
        o.CloseDate    = Date.today();
        o.StageName    = stage.masterlabel;
        Database.insert(o);

        /* Construct the standard controller for quote. */
        ApexPages.StandardController con = new ApexPages.StandardController(o);

        /* Switch to runtime context */
        Test.startTest();

        /* Construct the CustomOpp class */
       CloneOpportunityLineItems ext = new CloneOpportunityLineItems(con);
        
        PageReference result = ext.CloneOpportunityLineItems();

        /* Switch back to test context */
        Test.stopTest();
    }

    /* This setup method will create an opportunity with line items and a primary
       contact role for use in various tests. */
    private static Opportunity setupTestOpportunity() {

        /* Create an account */
        Account a = new Account();
        a.name    = 'TEST';
        Database.insert(a);

        /* Get the FY12 Global Price Book pricebook.  */
        
        Pricebook2 pb = [select id, name from PriceBook2 
            where name ='FY12 Global Price Book'];
           

        if(!pb.isactive) {
            pb.isactive = true;
            Database.update(pb);
        }
        
        Product2 pr = [select id from product2 limit 1];
        
        Pricebookentry pbe = [select id, CurrencyIsoCode, product2id, Pricebook2id
            from PriceBookEntry where Pricebook2id =: pb.id ];

        /* Get a valid stage name */
        OpportunityStage stage = [select MasterLabel from OpportunityStage limit 1];

        /* Setup a basic opportunity */
        Opportunity o  = new Opportunity();
        o.Name         = 'TEST';
        o.AccountId    = a.id;
        o.CloseDate    = Date.today();
        o.StageName    = stage.masterlabel;
        o.Pricebook2Id = pb.id;

        /* Create the opportunity */
        Database.insert(o);


        return o;
    }
}

 

Apex Class:

 

public class CloneOpportunityLineItems{

    private ApexPages.StandardController controller {get; set;}
    private Opportunity o {get;set;}
    public ID oid {get; set;}
         
    List<OpportunitylineItem> newOliList = new List<OpportunitylineItem>();
    
    List<OpportunityLineItem> newOLI = new List<OpportunityLineItem>([select id, pricebookentryid from OpportunityLineItem]);
    
    id FY12 = [select id from Pricebook2 where name = 'FY12 Global Price Book'].id;
    
    public CloneOpportunityLineItems(ApexPages.StandardController c) {
        o = (opportunity) c.getRecord();

        oid = System.currentpageReference().getParameters().get('oppid');

    }
  
    public PageReference CloneOpportunityLineItems() {
        Savepoint sp = Database.setSavepoint();
        
        List<OpportunitylineItem> oli = [select id, PriceBookEntry.Product2Id, PricebookEntry.Name, PriceBookEntry.id, Quantity,
            OpportunityId, TotalPrice, Cost_Each__c, Quote_Item_Number__c,UnitPrice,
            PriceBookEntry.PriceBook2id from OpportunityLineItem where Opportunityid =:oid];

        Map<ID, OpportunitylineItem> PRODMap = new Map<ID, OpportunitylineItem>();
 
                
        for(OpportunitylineItem ol : oli) {

            PRODMap.put(ol.PriceBookEntry.Product2id, ol);
  
        }
       
       system.debug('##############oli list is:' + oli);
       newOliList = oli;  
       system.debug('%%%%%%%%%%%%%%%' + oli);
              
       delete oli;
       
       system.debug('$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$' + newOliList);
       
       String[] pbenames = new String[]{};    // added by sfdc support; string list to store the pbe names from the old OLI's 
       
       for(OpportunityLineItem ol: newOliList){
           pbenames.add(ol.PricebookEntry.Name);    // Populating the list
           
       }
    
          Opportunity op = [select id, currencyisocode, Pricebook2.name from Opportunity where id =:oid limit 1];
      
          List<PricebookEntry> pbe = [select id, name, CurrencyIsoCode  from PriceBookEntry where
                                  Pricebook2id =: FY12 and Product2.id in: ProdMap.keySet() and
                                  currencyisocode =: op.currencyisocode];   
          
          Map<String, id> PbidAndNamesMap = new Map<String, id>();   // Added by sfdc support - Map to store pbe names and ids from the new query         
          
          for(PricebookEntry p: pbe){
              PbidAndNamesMap.put(p.Name, p.id);        // Populating the PbidAndNamesMap
          }
              
                            
      If(op.Pricebook2.name <> 'FY12 Global Price Book'){
          op.PriceBook2id = FY12;
      }
      update op;
     

    system.debug('***SFDC TEST ***************'+newOLI[0]);
    
    List<OpportunityLineItem> items = new List<OpportunityLineItem>();
    system.debug('##################### newOliList: ' + newOliList);
    
    Integer idx = 0;
    
    for(OpportunityLineItem ol : newOliList){

         OpportunityLineItem newOl = new OpportunityLineItem();
                          
           newOl.PricebookEntryId = PbidAndNamesMap.get(pbenames[idx]);    // Extracting the pbe ids based on the names from the PbidAndNamesMap and resolving the issue
           newOl.quantity = ol.quantity;
           newOl.OpportunityID = ol.OpportunityId;
           newOl.Cost_Each__c = ol.Cost_Each__c;
           newOl.UnitPrice = ol.UnitPrice;
           newOl.Quote_Item_Number__c = ol.Quote_Item_Number__c;
           items.add(newOl);
                               
           idx= idx+1;
}
 
               if(items.size() > 0)
                   system.debug('***items***************'+items);
                   insert items;
  
    PageReference pageRef = new PageReference('/' + oid);
    
     return pageref;

    }
}

 

Thank you,
ckellie

Best Answer chosen by Admin (Salesforce Developers) 
zachelrathzachelrath

As has already been noted, I'll bet anything that the source of your problem is this line:

 

Opportunity op = [select id, currencyisocode, Pricebook2.name from Opportunity where id =:oid limit 1];

 

From a brief glance at your basicSaveTest() test method, it appears that your CloneOpportunityLineItems controller is expecting to be passed an "oppId" parameter, which gets assigned to the "oid" variable in the above SOQL query. In order to simulate passing a query string parameter into a VF Controller in Test Code, you need to do something like this:

 

// Call a method which creates (and inserts) a test Opportunity
// and ALSO creates and inserts associated Line Items 
Opportunity testOpp = setupTestOpportunityWithLineItems();

PageReference testPage = Page.CloneOpportunityLineItems;

// Pass in the Id of the Opportunity whose Line Items
// you would like to clone
testPage.getParameters().put('oppid',testOpp.Id);

/* Navigate to your CloneOpportunityLineItems VF page */
Test.setCurrentPage(testPage);

 /* Construct the CustomOpp class */
ApexPages.StandardController stdCon 
    = new ApexPages.StandardController(testOpp);
CloneOpportunityLineItems ext = 
    new CloneOpportunityLineItems(stdCon);

 

So, 2 steps were missing:

1. Your setupTestOpportunity method needs to create and insert OpportunityLineItems related to your test Opportunity

2. You need to use the Test.setCurrentPage() method to simulate navigating to the VF page which uses CloneOpportunityLineItems.cls as its controller. 

All Answers

ngabraningabrani

Line number 51 is          

Opportunity op = [select id, currencyisocode, Pricebook2.name from Opportunity where id =:oid limit 1];


This line in method CloneOpportunityLineItems is generating the exception.

 

You need to print the value of oid through system.debug before line 51, and then try to debug if oid is set to some meaningful value or not.

 

In the class code, you could potentially assign the results of select to a list. If the list size is zero, then we do not perform some error handling.

 

zachelrathzachelrath

As has already been noted, I'll bet anything that the source of your problem is this line:

 

Opportunity op = [select id, currencyisocode, Pricebook2.name from Opportunity where id =:oid limit 1];

 

From a brief glance at your basicSaveTest() test method, it appears that your CloneOpportunityLineItems controller is expecting to be passed an "oppId" parameter, which gets assigned to the "oid" variable in the above SOQL query. In order to simulate passing a query string parameter into a VF Controller in Test Code, you need to do something like this:

 

// Call a method which creates (and inserts) a test Opportunity
// and ALSO creates and inserts associated Line Items 
Opportunity testOpp = setupTestOpportunityWithLineItems();

PageReference testPage = Page.CloneOpportunityLineItems;

// Pass in the Id of the Opportunity whose Line Items
// you would like to clone
testPage.getParameters().put('oppid',testOpp.Id);

/* Navigate to your CloneOpportunityLineItems VF page */
Test.setCurrentPage(testPage);

 /* Construct the CustomOpp class */
ApexPages.StandardController stdCon 
    = new ApexPages.StandardController(testOpp);
CloneOpportunityLineItems ext = 
    new CloneOpportunityLineItems(stdCon);

 

So, 2 steps were missing:

1. Your setupTestOpportunity method needs to create and insert OpportunityLineItems related to your test Opportunity

2. You need to use the Test.setCurrentPage() method to simulate navigating to the VF page which uses CloneOpportunityLineItems.cls as its controller. 

This was selected as the best answer
ckellieckellie

Thank you for the help and the education. It will help me on this class and others that I have like it.

 

Thank you