+ Start a Discussion
Tolga SunarTolga Sunar 

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

Hey,

I have the following method in which SOAP webservice is consumed created by wsdl2apex (only necessary part is shown):
 
public class SendOrder {
    
    public void SendOrder(string OrderId) {

        // Query for Order
        EFES_Order__c Order = [SELECT 	Id,
                               Ship_To_SAP_Code__c,
                               Sold_To_SAP_Code__c,
                               Currency__c,
                               Purchase_Order_Number__c,
                               Requested_Shipping_Date__c,
                               Original_Requested_Shipping_Date__c,
                               Shipping_Date_Change_Reason__c,
                               Incoterm__c,
                               Payment_Type__c,
                               Vehicle_Type__c,
                               Palette_Type__c,
                               Additional_Docs__c,
                               Logistics_Company_Phone__c,
                               Logistics_Company_Email__c,
                               Logistics_Company__c,
                               Order_SAP_Code__c,
                               Source_Country_Code__c,
                               Integration_Id__c,
                               Status__c
                               FROM Order__c 
WHERE Id=:OrderId];
        
.
.
.
.

        
        // Assign request parameters
.
.
.

        inputIM_Header.INCOTERMS 	= 	[SELECT Name FROM List_Of_Values__c WHERE Display_Value__c=:Order.Incoterm__c AND Type__c='INCOTERM' LIMIT 1].Name;
        inputIM_Header.PMNTTRMS 	= 	[SELECT Name FROM List_Of_Values__c WHERE Display_Value__c=:Order.Payment_Type__c AND Type__c='PAYMENT_TYPE' LIMIT 1].Name;          
        system.debug(inputIM_Header.PMNTTRMS);
        
.
.
.
.

    
        }
    	

}

I have also created a test class for this code, in which I first create a dataset and then call the above class inside it (again, only necessary part is shown):
 
@isTest(SeeAllData=true)
private class EFES_SendOrder_Test {

    static testMethod void OrderTest() {
        
        List_Of_Values__c ListOfValue2 = new List_Of_Values__c();
        ListOfValue2.Name = 'INCO';
        ListOfValue2.Display_Value__c = 'Incoterm';
        ListOfValue2.Type__c = 'INCOTERM';
        insert ListOfValue2;
        system.debug('listofvalue2 id = '+ListOfValue2.id);
        
        List_Of_Values__c ListOfValue3 = new List_Of_Values__c();
        ListOfValue3.Name = 'PMNT';
        ListOfValue3.Display_Value__c = 'Payment';
        ListOfValue3.Type__c = 'PAYMENT_TYPE';
        insert ListOfValue3;
	system.debug('listofvalue3 id = '+ListOfValue3.id);
        
.
.
.
.

                
        Order__c Order = new Order__c();
        Order.ShipTo_Account__c = ShipToAccount.Id;
        Order.Currency__c = 'USD';
	Order.Source_Country_Code__c = 'TURKEY';
	Order.Requested_Shipping_Date__c = system.today();
	Order.Original_Requested_Shipping_Date__c = system.today();
	Order.Incoterm__c = 'Incoterm';
	Order.Payment_Type__c = 'Payment';        
        insert Order;
        system.debug('order id = '+Order.id);
        
.
.
.
.
               
        Test.startTest();
        
        SendOrder SendOrderx = new SendOrder();
		SendOrderx.SendOrder(Order.Id);
        
        Test.stopTest();

.
.
.
.

    }
}

According to the test data, inputIM_Header.INCOTERMS and inputIM_Header.PMNTTRMS queries should not return blank, because I create exact data for both of them. However, when I run the test, INCOTERMS is populated, while PMNTTRMS query does not see the test data and I get the error specified in the title. 

I've made a lot of research about that;
  • I had already SeeAllData on, turning it off was no help,
  • I'm on SystemAdmin user so I have all the permissions,
  • I debug all the test data and make sure they all are created on test class,
  • Debugging PMNTRMS returns a data when executed from execute anonymous (testing with org data),
  • Payment_Type__c FLS is OK for SystemAdmin
The fact that bug me most is that INCOTERMS is fine while PMNTTRMS could not be queried.

P.S. I know you are going to tell me to use List instead of a single sObject; you are right, but I am getting NO record from query at this point. I want to solve it first.

Any help is greatly appreciated. Thanks in advance.
 
Best Answer chosen by Tolga Sunar
Tolga SunarTolga Sunar
Update: When I queried for the order I created in test class, I saw that the Payment_Type__c field was indeed null. That's why test was failing. Hence I re-typed the test class block into as below:
 
Order__c Order = new Order__c();        
Order.ShipTo_Account__c = ShipToAccount.Id;
Order.Currency__c = 'USD';
Order.Source_Country_Code__c = 'TURKEY';
Order.Requested_Shipping_Date__c = system.today();
Order.Original_Requested_Shipping_Date__c = system.today();
insert Order;
        
Order__c OrderUpdate = [SELECT Id, Incoterm__c, Payment_Type__c FROM Order__c WHERE Id=:Order.Id];
OrderUpdate.Incoterm__c = 'Incoterm';
OrderUpdate.Payment_Type__c = 'Payment';
update OrderUpdate;

This did the trick. Class subject to testing is reverted to its original state. But I really want to know why, at first, Payment Type field did not get populated (it's a picklist field). I appreciate any clarification on this.

All Answers

Shashikant SharmaShashikant Sharma
Hi Tolga,

First make sure the queries are returning results by running them in Developer Console. If that is fine then.

Make your class declaration as without sharing
 
public without sharing class SendOrder

Let me know if it works or you are still having issue.

Thanks
Shashikant
Tolga SunarTolga Sunar
Hey Shashikant,

Unfortunately this declaration did not help. 

By the way, I'm aware that there are some mismatches is my code; I was trying to clear all the "EFES_" tags but apparently I've skipped some. Please ignore them.
Shashikant SharmaShashikant Sharma
Hi,

Please do one thing.

In your test class where you are inserting 

insert ListOfValue3;

Make this query just after that
 
System.assert( fasle, [SELECT Name, Type__c, Display_Value__c FROM List_Of_Values__c WHERE Display_Value__c= 'Payment' AND Type__c='PAYMENT_TYPE' Where Id =: ListOfValue3.Id ] );

This will make test method fail but this is to check make sure there is no trigger or workflow which is changing the Dispaly Value or Type.

Share the result of this.

Thanks
Shashikant
 
Tolga SunarTolga Sunar
Below is the query and debug result right after List Of Values record is created in test class. Record is created and undergo no change.
 
08:07:32:104 USER_DEBUG [33]|DEBUG|(List_Of_Values__c:{Name=PMNT, Type__c=PAYMENT_TYPE, Display_Value__c=Payment, Id=a0C4E000000mtnLUAQ})

By the way, Incoterm and Payment Type fields on Order object are of picklist type. I assign values to them in Order test record which are not defined in SF org as picklist values. I've also tested against it, but it made no difference.
Shashikant SharmaShashikant Sharma
Now one more debug in class SendOrder just before the Query to check order.payment_type__c value.
 
system.debug('********* Order : ' + Order.Payment_Type__c );
inputIM_Header.PMNTTRMS    =   [SELECT Name FROM List_Of_Values__c WHEREDisplay_Value__c=:Order.Payment_Type__c AND Type__c='PAYMENT_TYPE' LIMIT 1].Name;

One more thing that could you change your method name to something else than SendOrder as it is the name of class. You may name it sendOrderAction


Thanks


 
Tolga SunarTolga Sunar
Hey,

How am I going to read this debug in class when I run the test class? Could you instruct me please?

By the way, I have found a workaround. First, I define a public string variable in the class:
 
public class SendOrder {
    
    public string IMHeader_PMNTTRMS;
    
    public void SendOrder(string OrderId) {

I put the following logic in the class:
 
if ([SELECT Name FROM List_Of_Values__c WHERE Display_Value__c=:Order.Payment_Type__c AND Type__c='PAYMENT_TYPE'].size()>0) {
        	IMHeader_PMNTTRMS = [SELECT Name FROM List_Of_Values__c WHERE Display_Value__c=:Order.Payment_Type__c AND Type__c='PAYMENT_TYPE' LIMIT 1].Name;          
        }

.
.
.
inputIM_Header.PMNTTRMS 	= 	IMHeader_PMNTTRMS;

Then I define this string in the test class after creating an instance of the class, before executing the inner class:
 
SendOrder SendOrder = new SendOrder();
SendOrder.IMHeader_PMNTTRMS = 'Blah';
SendOrder.SendOrder(Order.Id);

By this way I'm able to go around this weird behavior and pass the test & get enough coverage.

For the note; I remove the namespaces in class names here, so in the actual code, class, inner class and variable names don't all look alike.

But, it does not mean that I'm now done; I'll go on this issue with all my available force.

Cheers
Tolga SunarTolga Sunar
Update: When I queried for the order I created in test class, I saw that the Payment_Type__c field was indeed null. That's why test was failing. Hence I re-typed the test class block into as below:
 
Order__c Order = new Order__c();        
Order.ShipTo_Account__c = ShipToAccount.Id;
Order.Currency__c = 'USD';
Order.Source_Country_Code__c = 'TURKEY';
Order.Requested_Shipping_Date__c = system.today();
Order.Original_Requested_Shipping_Date__c = system.today();
insert Order;
        
Order__c OrderUpdate = [SELECT Id, Incoterm__c, Payment_Type__c FROM Order__c WHERE Id=:Order.Id];
OrderUpdate.Incoterm__c = 'Incoterm';
OrderUpdate.Payment_Type__c = 'Payment';
update OrderUpdate;

This did the trick. Class subject to testing is reverted to its original state. But I really want to know why, at first, Payment Type field did not get populated (it's a picklist field). I appreciate any clarification on this.
This was selected as the best answer