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
Marty DorrenMarty Dorren 

"List has no rows for assignment to Sobject" error, but works as SOQL query

Hello,
I have a visualforce page with a custom controller.  The custom controller fills in some information in the header of my datatable:

timesheetOwner = [select service_staff__r.name from service_documentation__c where service_staff__c = 'a23M0000001A6FjIAK' limit 1].service_staff__r.name;

In the anon window, the following code also works:

timesheetOwner = [select service_staff__r.name from service_documentation__c where service_staff__c = 'a23M0000001A6FjIAK' limit 1].service_staff__r.name;
system.debug('timesheetowner = '+timesheetowner);

This works fine on my VF page, but when I try to test and deploy to production, I get the "List has no rows for assignment to Sobject" error.  In placing various debug lines in the code, sure enough, the variable shows as null.... however, when I take the SOQL select and place it in the query editor, it works... Very confusing...

Originally, the implicit service_staff__c filter used a variable and gave the same error.  I then tried the select with the literal content and got the same error.

So in a nutshell:
I have a line of code that for all practical purposes... works
The line doesn't work when testing
The code won't deploy for the same reason

Any ideas?

Thanks,
Marty
Best Answer chosen by Marty Dorren
bob_buzzardbob_buzzard
Its a very common scenario. The solution is for your test class to create the data it relies on I'm afraid - there's no short cut that will work across sandbox and production orgs.

All Answers

bob_buzzardbob_buzzard
This sounds like the id 'a23M0000001A6FjIAK' is specific to a record in your sandbox (or wherever you are creating the code), but doesn't exist in production (which is highly likely I would say).  Unit tests are isolated from production data by default nowadays, so they won't be able to see that record. 
Marty DorrenMarty Dorren
I can see where that would make sense.  Thanks Bob.  So, I have code that executes fine, but will not deploy to production?  Also, keep in mind that the "actual" code is referencing a variable.  As a debugging tool, I placed the implicit content in the statement.  Using the variable yielded the same error however.... hmmmm...
Marty
bob_buzzardbob_buzzard
That still smacks that you are relying on existing data in the unit test - instead of this, the test should insert the data that it relies on as part of the test setup - that way, wherever it is installed, the test will still be able to execute successfully.

What is the variable referencing? How does the value get set up?
Marty DorrenMarty Dorren
Interesting.  The variable is an id in the url that calls the VF page..  That being said, if my test class calls the method as in:

@isTest
private class SD_Time_Cntl_Test {     
static testmethod void SDCntlTest(){         
PageReference pg = Page.SD_Timesheet;         
Test.setCurrentPage(pg);         
pg.getParameters().put('sid','a23M0000001A6Fj');         
pg.getParameters().put('start','1');         
pg.getParameters().put('schart','a0DM0000008irhH');         
SD_Time_Cntl controller = new SD_Time_Cntl();         
System.assert(controller.MyMethode() == null);         
System.assert(controller.reset() == null);         
System.assert(controller.save() == null);         
System.assert(controller.filterreset() == null); }
}

BTW, The method in question is reset()
bob_buzzardbob_buzzard
Yeah, so the issue is much the same - you are passing a hardcoded id into the URL that the test class doesn't have access to.  Even if you gave the test class access in the sandbox, the chances are that the production org wouldn't contain the same data and thus the unit tests would fail, stopping your deployment.
Marty DorrenMarty Dorren
Sorry for the delay... lunch.  Soooo... How can I circumnavigate this?  It MUST be a typical scenario yes?
Marty
bob_buzzardbob_buzzard
Its a very common scenario. The solution is for your test class to create the data it relies on I'm afraid - there's no short cut that will work across sandbox and production orgs.
This was selected as the best answer
Marty DorrenMarty Dorren
Hi,
Live and learn I suppose.  So the process would be a series of database.saveresult[] additions till i construct my environment.  Many thanks for your time.
Marty
Marty DorrenMarty Dorren
Afraid I spoke to soon...

The getparameters().put statement for schart doesn't seem to be staying current when brought to my reset() method.  It seems that @istest is deleting the record that Iconstructed before giving the method a chance to reference it.  How can I keep the temporary records valaid till the method is done with them?  Thanks... oh... btw... here's my test code:

@isTest
private class SD_Time_Cntl_Test {
    static testmethod void SDCntlTest(){
        PageReference pg = Page.SD_Timesheet;
        Test.setCurrentPage(pg);
//set up test data
date tdy = system.date.today();
//set up contact
    Id CO_IND_RecType = [select Id,name from RecordType where name='Individual Served' and SObjectType='contact' limit 1].Id;
    Id CO_Staff_RecType = [select Id,name from RecordType where name='Staff' and SObjectType='contact' limit 1].Id;
    string tmpstf;
    string tmpind;
    string whatcon;
    string whatind;
    string tmpstfname;
            
            List<Contact> CONCreate = new List<Contact>();
            CONCreate.add (new Contact(
                Salutation = 'Mr.',
                FirstName = 'IT',
                LastName = 'Individual',
                Gender__c = 'Male',
                npe01__Preferred_Email__c = 'Home',
                npe01__AlternateEmail__c = 'altemail@ldagvi.org',
                npe01__WorkEmail__c = 'workemail@ldagvi.org',
                npe01__HomeEmail__c = 'homeemail@ldagvi.org',
                npe01__PreferredPhone__c = 'Work',
                Social_Security_Number__c = '111-11-1111',
                MobilePhone = '585-263-3323',
                npe01__WorkPhone__c = '585-263-3323',
                OtherPhone = '585-263-3323',
                Ethnicity__c = 'Caucasian/White',
                RecordTypeId = CO_IND_RecType));
                tmpind = CO_IND_RecType;

            CONCreate.add (new Contact(
                Salutation = 'Mr.',
                FirstName = 'IT',
                LastName = 'Staff',
                Gender__c = 'Male',
                npe01__Preferred_Email__c = 'Home',
                npe01__AlternateEmail__c = 'altemail@ldagvi.org',
                npe01__WorkEmail__c = 'workemail@ldagvi.org',
                npe01__HomeEmail__c = 'homeemail@ldagvi.org',
                npe01__PreferredPhone__c = 'Work',
                Social_Security_Number__c = '111-11-1111',
                MobilePhone = '585-263-3323',
                npe01__WorkPhone__c = '585-263-3323',
                OtherPhone = '585-263-3323',
                Ethnicity__c = 'Caucasian/White',
                RecordTypeId = CO_Staff_RecType));
                tmpstf = CO_Staff_RecType;


            Database.SaveResult[] CONList = Database.insert(CONCreate);

                list<contact> conlist2 = new list<contact>();

            for (Database.SaveResult srCON : CONList) {
                system.debug('conlist = '+conlist);
                system.debug('srcon = '+srcon);

                if (srCON.isSuccess()) {
                    CONlist2.add (new Contact(
                    id = srCON.getId()));
                    // Operation was successful, so get the ID of the record that was processed
                    System.debug('Successfully inserted contact. Contact ID: ' + srCON.getId());
                    whatCON = srCON.getId();
                }
                else {
                    // Operation failed, so get all errors                
                    for(Database.Error err : srCON.getErrors()) {
                        System.debug('The following error has occurred.');                    
                        System.debug(err.getStatusCode() + ': ' + err.getMessage());
                        System.debug('Account fields that affected this error: ' + err.getFields());
                        whatIND = srCON.getId();
                    }
                }  
            }
list<contact> conlist3 = [select recordtypeid,id, name from contact where id IN :conlist2];
for(contact conloop2 : conlist3){
if(conloop2.recordtypeid == CO_Staff_RecType){
tmpstf = conloop2.id;
tmpstfname = conloop2.name;
}
if(conloop2.recordtypeid == CO_IND_RecType){
tmpind = conloop2.id;
}
}

            system.debug('conlist2 = '+conlist2);
            system.debug('tmpstf = '+tmpstf);
            system.debug('tmpind = '+tmpind);
        
//set up service chart
    Id SDRecTypeFI = [select Id,name from RecordType where name='FI' and SObjectType='service_documentation__c' limit 1].Id;
    Id SDRecTypeFILock = [select Id,name from RecordType where name='FI - Locked' and SObjectType='service_documentation__c' limit 1].Id;    
    string tmpchart;
    string whatip;

            List<individual_programs__c> IPCreate = new List<individual_programs__c>();

            IPCreate.add (new individual_programs__c(
                individual__c = tmpind,
                status__c = 'Enrolled',
                enroll_date__c = tdy,
                primary_client__c = 'Person With a Disability'));

            Database.SaveResult[] IPList = Database.insert(IPCreate);

                list<individual_programs__c> iplist2 = new list<individual_programs__c>();

            for (Database.SaveResult ipCON : ipList) {
                system.debug('iplist = '+iplist);
                system.debug('ipcon = '+ipcon);

                if (ipCON.isSuccess()) {
                    // Operation was successful, so get the ID of the record that was processed
                    System.debug('Successfully inserted individual program. IP ID: ' + ipCON.getId());
                    whatIP = ipCON.getId();
                }
                else {
                    // Operation failed, so get all errors                
                    for(Database.Error err : ipCON.getErrors()) {
                        System.debug('The following error has occurred.');                    
                        System.debug(err.getStatusCode() + ': ' + err.getMessage());
                        System.debug('Account fields that affected this error: ' + err.getFields());
                        whatip = ipCON.getId();
                    }
                }  
            }
tmpchart = [select name from individual_programs__c where id = :whatip limit 1].name;
system.debug('tmpchart = '+tmpchart);


            List<service_staff__c> SSCreate = new List<service_staff__c>();

            SSCreate.add (new service_staff__c(
                staff_contact__c = tmpstf,
                service_chart__c = tmpchart,
                start_date__c = tdy,
                name = tmpstfname));

            Database.SaveResult[] SSList = Database.insert(SSCreate);
            for (Database.SaveResult SSCON : SSList) {
                system.debug('sslist = '+sslist);
                system.debug('sscon = '+sscon);

                if (ssCON.isSuccess()) {
                    // Operation was successful, so get the ID of the record that was processed
                    System.debug('Successfully inserted service staff. ss ID: ' + ssCON.getId());
                }
                else {
                    // Operation failed, so get all errors                
                    for(Database.Error err : ssCON.getErrors()) {
                        System.debug('The following error has occurred.');                    
                        System.debug(err.getStatusCode() + ': ' + err.getMessage());
                        System.debug('Account fields that affected this error: ' + err.getFields());
                        whatip = ssCON.getId();
                    }
                }  
            }
        
        system.debug('test sid = '+tmpstf);
        pg.getParameters().put('sid',tmpstf);
        pg.getParameters().put('start','1');
        pg.getParameters().put('schart',tmpchart);

        SD_Time_Cntl controller = new SD_Time_Cntl();

        System.assert(controller.reset() == null);
        System.assert(controller.MyMethode() == null);
        System.assert(controller.save() == null);
        System.assert(controller.filterreset() == null);
}
}

Marty