0

I have searched on here for a case that is similar to my own, but I can't find anything that matches why I'm getting the SQL error in my test. I'm very new to Apex and have been editing/duplicating code from a previous developer.

Error =

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

Does anyone know why this would be failing? The trigger works in the sandbox but it will not let me deploy to production as the test fails.

Here is my class test:

@isTest
public class OppReSEMTest {
        public static testMethod void Tester() {

    OpportunityLineItem oli = [select Id,OpportunityId from OpportunityLineItem
                                        where PricebookEntry.Product2.Production_Item__c=true
                                        limit 1];

    Opportunity o = [select Id,StageName,Finance_VAT_Exempt__c,Sector__c,

                                        PO_Number__c,Finance_Email__c from Opportunity
                                               where Id=:oli.OpportunityId
                                               limit 1];   

    o.StageName='Closed Lost';
    o.Finance_VAT_Exempt__c='Yes';
    update o;
    o.StageName='Closed Won';
    o.Finance_VAT_Exempt__c='Yes';
    o.PO_Number__c='0987654';
    o.Finance_Email__c='craig@test.com';
    o.Sector__c='Charity';
    update o;
    }

}

Here is my trigger:

trigger OppReSEM on Opportunity (after insert, after update) {
    try {
        if (Test.isRunningTest() || ! OnceSEM.hasAlreadyRound()) {
            set<id> oids = new set<id>();

            for (Opportunity o:trigger.new) {
                    if (trigger.newMap.get(o.id).Create_New_Production_Orders__c == TRUE)
                {
                    oids.add(o.id);
        }
            }
            system.debug('!!!!!!!!!!!!!!!!oids size!!!!!!' + oids.size());

            if (oids.size() > 0) {
                list<OpportunityLineItem> loli = ([
                    select Id,
                    Opportunity.Id,
                    Opportunity.Name,
                    Quantity,
                    Account__c,
                    PricebookEntry.Product2.Id,
                    PricebookEntry.Product2.Name
                    from
                    OpportunityLineItem
                    where Opportunity.Id IN: oids
                    and
                    PricebookEntry.Product2.Quantity_Override__c=true
                    and
                    OpportunityLineItem.Production_Order_Created__c=false
                ]);

                system.debug('!!!!!!!!!!!!!!!!loli size!!!!!!' + loli.size());


                if (loli.size() > 0) {
                    OnceFO.setAlreadyRound();

                    list<Sales_Order__c> li = new list<Sales_Order__c>();

                    for (OpportunityLineItem oli : loli) {
                        string semn = (oli.PricebookEntry.Product2.Name + ' | ' + oli.Opportunity.Name + ' | ' + oli.Account__c);

   //Get sizes of Goal and Strategy in the event they are longer than 80 char and need to be truncated
   Integer size1 = semn.length();


   //If Goal or Strategy are longer than 80 characters they need to be truncated
   if(size1> 80){
         semn= semn.substring(0, 79);
   }
                        Sales_Order__c so = new Sales_Order__c(
                            Name=semn,
                            Opportunity__c=oli.Opportunity.Id,
                            Product__c=oli.PricebookEntry.Product2.Id
                        );
                        li.add(so);
                        if (li.size() > 198) {
                            insert li;
                            li.clear();
                        }
                    }
                    if (li.size() > 0) {
                        insert li;
                        li.clear();
                    }
                }
            }
        }
    } catch (Exception exall) {}
}

Here is my class:

public class OnceSEM {
      private static boolean alreadyRound = false;
    public static boolean hasAlreadyRound() {
        return alreadyRound;
    }
   public static void setAlreadyRound() {
        alreadyRound = true;
    }


}
  • Are you using an ancient API version on your test class? SeeAllData has been false by default since 23.0. – Adrian Larson Aug 30 '17 at 18:03
2

See the Apex Developer Guide (emphasis mine):

Isolation of Test Data from Organization Data in Unit Tests

Starting with Apex code saved using Salesforce API version 24.0 and later, test methods don’t have access by default to pre-existing data in the organization, such as standard objects, custom objects, and custom settings data, and can only access data that they create. However, objects that are used to manage your organization or metadata objects can still be accessed in your tests such as:

  • User
  • Profile
  • Organization
  • AsyncApexJob
  • CronTrigger
  • RecordType
  • ApexClass
  • ApexTrigger
  • ApexComponent
  • ApexPage

Whenever possible, you should create test data for each test. You can disable this restriction by annotating your test class or test method with the IsTest(SeeAllData=true) annotation.

Test code saved using Salesforce API version 23.0 or earlier continues to have access to all data in the organization and its data access is unchanged.

So you need to create Opportunity and OpportunityLineItem records for your test to work in a predictable manner across environments.

Opportunity parent = new Opportunity(/*any required fields*/);
insert parent;

OpportunityLineItem child = new OpportunityLineItem(OpportunityId=parent.Id /*any other required fields*/);
insert child;

// update records

Please also note from How to Write Good Unit Tests (emphasis mine):

Verify the results are correct

Verifying that your code works as you expect it to work is the most important part of unit testing. It’s also one of the things that Force.com developers commonly neglect. Unit tests that do not verify the results of the code aren’t true unit tests. They are commonly referred to as smoke tests, which aren’t nearly as effective or informative as true unit tests.

A good way to tell if unit tests are properly verifying results is to look for liberal use of the System.assert() methods. If there aren’t any System.assert() method calls, then the tests aren’t verifying results properly. And, no, System.assert(true); doesn’t count.

| improve this answer | |
  • Thanks Adrian! As I said I've interited this code. It was written in 23.0, I've updated the tests and now they are working. Thanks for your help! – James Whiting Aug 30 '17 at 19:58

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.