1

I am trying to create a unit test for an Apex class that creates a series of records in other tables and then takes the user to one of the new records. This process all starts from a button on the starting record. It calls a Visualforce page that then triggers the Apex class to run.

This all works fine. The problem is in the unit test. I get an error "System.QueryException: List has no rows for assignment to SObject". At this point I am sure the issue is in my test code, the page being setup for the test doesn't have the required ID in it.

All the searching I have done says that you have to set it via a "pageRef.getParameters().put('id', ". Line 21 in my code. I have this, I think, correctly and it still isn't working. You can also see some of the other formats that I have run across and tried as well. None work. What am I doing wrong here? This is only the second unit test I have written, so still learning. SF Trailhead classes have only gone so far. :)

Here is the unit test that I am working with.

@isTest
private class SendItem_UnitTest {

private static testMethod void testAutoRun() {

    test.startTest();
    //Create a sample SON to be used for unit test
    SalesOrder__c SON = new SalesOrder__c(CurrencyIsoCode = 'USD',SON_Status__c='Approved');
    insert SON;
    //Create a sample Items Purchased for unit test
    ItemPurchased__c iPurchased = new ItemPurchased__c(SalesOrder__c=SON.Id,Product__c='01tw0000005GBsm',
                                                       CurrencyIsoCode='USD',Quantity__c=1);
    insert iPurchased;
    //Id Testid = iPurchased.Id;

    ApexPages.StandardController sc = new ApexPages.standardController(iPurchased);
    SendItem testSendItem = new SendItem(sc);

    PageReference pageRef = Page.SendItem;
    Test.setCurrentPage(pageRef);
    ApexPages.currentPage().getParameters().put('id',iPurchased.Id);
    //pageRef.getParameters().put('id',iPurchased.Id);
    //pageRef.getParameters().put('id', String.valueOf(iPurchased.Id));

    SendItem.autorun();
    List<ItemSent__c> lstopp =[select id from ItemSent__c where Item_Purchased_Number__c=: iPurchased.id];
    System.assertequals(1,lstopp.size());

    test.stopTest();
}
} 

I think my problem is around the pageref setup, but have no idea what I am doing wrong here.

In case it helps, here is the Apex Class as well.

public class SendItem {

// Constructor - this only really matters if the autoRun function doesn't work right
private final ItemPurchased__c ip;
public SendItem(ApexPages.StandardController stdController) {
    this.ip = (ItemPurchased__c)stdController.getRecord();
}

// Code we will invoke on page load.
public static PageReference autoRun() {

    String theId = ApexPages.currentPage().getParameters().get('id');

    if (theId == null) {
        // Display the Visualforce page's content if no Id is passed over
        return null;
    }
    //String that will be used for the page redirection at the end of process.
    string isId = '';

    // Create the ItemSent and Entitlement records.
    // Start by collecting the data needed for the rest of the process
    for (ItemPurchased__c record:[select Id, Product__r.Name, AdditionalInformation__c, LicenceDuration__c,
                                  LicenceType__c, SalesOrder__c, CurrencyIsoCode, TrainingDate__c
                                  from ItemPurchased__c where id =:theId]) {

                                      //Create variables to be used for this step.
                                      Date dateToday = date.today();
                                      //Display date for the different name fields being created.
                                      Datetime displayDate2 = Datetime.now();
                                      String displayDate = displayDate2.format('yyyymmmmdd');

                                      ItemSent__c newIS = new ItemSent__c(
                                          Item_Purchased_Number__c = record.Id,
                                          Product__c = record.Product__r.Name,
                                          AdditionalInformation__c = record.AdditionalInformation__c,
                                          LicenceDurationAdditionalInfo__c = record.LicenceDuration__c,
                                          LicenceType__c = record.LicenceType__c,
                                          SalesOrder__c = record.SalesOrder__c,
                                          Stage__c = 'Links delivered',
                                          CurrencyIsoCode = record.CurrencyIsoCode,
                                          TrainingDate__c = record.TrainingDate__c
                                      );
                                      try{
                                          insert newIS;
                                          isId = newIs.Id;

                                      } catch (System.CalloutException e){
                                          System.debug('ERROR Creating the Item Sent record:' + e);
                                      }

                                      //SOQL query to get Service Contract ID info for correct linking
                                      ServiceContract scInfo = [SELECT Id, AccountId FROM ServiceContract WHERE SalesOrder__c = :record.SalesOrder__c];

                                      //Create the Entitlement record
                                      Entitlement newEntitlement = new Entitlement(
                                          Name = displayDate + record.Product__r.Name,
                                          AccountId = scInfo.AccountId,
                                          ServiceContractId = scInfo.Id,
                                          ItemSent__c = newIS.Id,
                                          StartDate = dateToday,
                                          EndDate = dateToday.addYears(1)
                                      );
                                      try{
                                          insert newEntitlement;            
                                      } catch (System.CalloutException e){
                                          System.debug('ERROR Creating the Item Sent record:' + e);
                                      }
                                  }

    // Redirect the user
    PageReference pageRef = new PageReference('/' + isId);
    pageRef.setRedirect(true);
    return pageRef;

}
}

Thanks for any help

3
  • Where does the List has no rows error occur? Mar 7, 2018 at 22:40
  • why is autoRun a static method? - if it is invoked with page action, should be instance method
    – cropredy
    Mar 7, 2018 at 22:42
  • DavidCheng, The error says it happens at line 53 of my SendItem script. It is trying to find the info on my ServiceContract record, which as sfdcfox pointed out below, doesn't seem to exist. I am working on fixing that issue now and see what happens. -- cropredy, Still learning Apex Coding, so copy paste of code I found that seems to do what I want, it works so I left it alone. Any pointers on a good place to better understand 'static' verse 'instance' and why?
    – PHonnold
    Mar 8, 2018 at 14:24

1 Answer 1

1

Your error is here:

ServiceContract scInfo = [SELECT Id, AccountId FROM ServiceContract WHERE SalesOrder__c = :record.SalesOrder__c];

Nowhere in your test or autoRun method are you creating a ServiceContract. If it's elsewhere, you failed to demonstrate that code. However, I'm pretty sure that this is where your problem is. There's no ServiceContract, so your code fails with the QueryException. Make sure you're inserting one first.

As a side note:

} catch (System.CalloutException e){

Is not the correct exception to catch here. If an exception occurs, it will be a DmlException. And if you get an exception, do not continue processing afterwards; you need to abort and let the user know an error occurred.

Also, don't use hard-coded ID values in your code (e.g. the Product ID that you use in the test). Make sure you query for the record and/or insert one as appropriate.

3
  • this script is the second part of a process that my users work with in SF. The service contract record has already been created someplace else, in another process. BUT, for a unit test that isn't the case and there is no service contract records for this process. I think you are onto something there. Let me look at fixing that and see what happens. I will also look into the other, DmlException item. New to Apex coding, so don't understand all I know I need to. Thanks,
    – PHonnold
    Mar 8, 2018 at 14:20
  • Marking this as the answer as this helped me fix it. I had created all the testing data, but for this service contract record. Once that was in place the test past. Just need to finish the coverage of all the code and options of my script now. Thanks for the second set of eyes and help with this.
    – PHonnold
    Mar 8, 2018 at 15:09
  • @PHonnold Great! Glad I could get you going.
    – sfdcfox
    Mar 8, 2018 at 15:28

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .