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

I have searched for this error, but it seems specific to what your trying to do.

When i test this code on my sandbox, I get over 90% code coverage. When i push to my production environment, I get the following error:

System.QueryException: List has no rows for assignment to SObject
Stack Trace: Class.TestFireFighterTickets_createFFticket.testFireFighter: line 6, column 1

Do I need a try catch exception for this to pass? If when i try using

try {
    insert ftix;
}   catch (system.Dmlexception e){
system.debug(e); }

It does not work

My apex trigger:

trigger FireFighterticketcreatorTrigger on Help_Desk_Ticket__c (after update) {
List<Firefighter__c> ftix = new List<Firefighter__c>(); 
for (Help_Desk_Ticket__c hd:trigger.new) {
    if (hd.OwnerId == '0050B0000073uze')
    {
        Firefighter__c ff = new Firefighter__c ();
        ff.Email_Address__c = hd.Email_Address__c;
        ff.EmailFromName__c = hd.EmailFromName__c;
        ff.OwnerId            = '0050B0000073uze';
        ff.Description__c   = hd.Description__c;
        ff.Title__c         = hd.Title__c;
        ff.Internal_Notes__c= hd.Internal_Notes__c;
       ftix.add(ff);
    } } 
try {
    insert ftix;
}   catch (system.Dmlexception e){
system.debug(e);}}

My test class:

@isTest(SeeAllData=true)

private class TestFireFighterTickets_createFFticket {  
static testmethod void testFireFighter() {
    Test.startTest();
    Help_Desk_Ticket__c hd = [
        select id,
          EmailFromName__c
        from Help_Desk_Ticket__c
        where OwnerId = '0050B0000073uze'
        limit 1];
    System.assert(hd != null);

    hd.EmailFromName__c = 'fighterfighter@glgroup.com';
    update hd;
    Test.stopTest();

    List<Firefighter__c> ffs = [
        select id
        from Firefighter__c
        where EmailFromName__c = :hd.EmailFromName__c];
    System.assertEquals(1, ffs.size());
}}

Best Answer

Your issue with both your trigger and your test class are because you've hardcoded a userId into your code. This is a very poor practice. You're much safer to select a profile to use for the user who will have the correct permissions to perform the operation.

Further, the user in your sandbox will have a different Id in production than in your sandbox. Regardless, it's not clear why you'd want to limit your trigger to a single user. If you in fact did need this requirement, for security reasons, you'd want to do one of the following to retrieve the userId during runtime:

  • store it in a custom setting
  • store it in custom metadata

Your test should also use a "RunAs" user. Here's more on the RunAs user and best practices for using one in a unit test:

private class TestRunAs {
   public static testMethod void testRunAs() {
      // Setup test data
      // This code runs as the system user
      Profile p = [SELECT Id FROM Profile WHERE Name='Standard User']; 
      User u = new User(Alias = 'standt', Email='standarduser@testorg.com', 
      EmailEncodingKey='UTF-8', LastName='Testing', LanguageLocaleKey='en_US', 
      LocaleSidKey='en_US', ProfileId = p.Id, 
      TimeZoneSidKey='America/Los_Angeles', UserName='standarduser@testorg.com');
      // Role = 'some Role'; this would be specific to your org if it uses roles

      System.runAs(u) {
      // The following code runs as user 'u' 
      System.debug('Current User: ' + UserInfo.getUserName());
      System.debug('Current Profile: ' + UserInfo.getProfileId()); }
   }
}

You can nest more than one runAs method. For example:

@isTest
private class TestRunAs2 {

   public static testMethod void test2() { 

      Profile p = [SELECT Id FROM Profile WHERE Name='Standard User']; 
      User u2 = new User(Alias = 'newUser', Email='newuser@testorg.com', 
         EmailEncodingKey='UTF-8', LastName='Testing', LanguageLocaleKey='en_US', 
         LocaleSidKey='en_US', ProfileId = p.Id, 
         TimeZoneSidKey='America/Los_Angeles', UserName='newuser@testorg.com');
         Role='Support'; // again, specific to your org. 
      System.runAs(u2) {
         // The following code runs as user u2. 
         System.debug('Current User: ' + UserInfo.getUserName());
         System.debug('Current Profile: ' + UserInfo.getProfileId()); 

         // The following code runs as user u3. 
         User u3 = [SELECT Id FROM User WHERE UserName='newuser@testorg.com'];

         System.runAs(u3) {
            System.debug('Current User: ' + UserInfo.getUserName());
            System.debug('Current Profile: ' + UserInfo.getProfileId()); 
         }

         // Any additional code here would run as user u2.
      }
   }
}

Best Practices for Using runAs

The following items use the permissions granted by the user specified with runAs running as a specific user:

Dynamic Apex

Methods using with sharing or without sharing

Shared records

The original permissions are reset after runAs completes.

The runAs method ignores user license limits. You can create new users with runAs even if your organization has no additional user licenses.