[SalesForce] Bind Variable Issue with SOQL Query in Test Class

I'll admit outright, I'm a beginner when it comes to Apex, so I apologize if anyone's addressed this already or if I'm missing something obvious, but:

I'm trying to write a test class to cover my code on a trigger that I've already determined is executing as I'd like (in our sandbox), but I can't get the test class to pass. The exception it keeps throwing when it fails is "System.QueryException, List has no rows for assignment to SObject."

The line that throws the error is one of the queries (Merchant__c and Location__c are both custom objects, merchant is parent in master-detail relationship). Given that this is the trouble spot, I'm assuming my error is with the bind notation?? But I really don't understand why this wouldn't return anything, especially as I've tested the query in the Developer Console (obviously without the bind notation), and it worked fine.

l3 = [ SELECT Merchant__c FROM Location__c WHERE Name = :locName ];   

To show the whole class, it's

@isTest
private class testCreateLocationsFromOpportunity {

     static testMethod void myAddLocToExistingMerchantTest() {

        Account a3 = new Account( Name = 'TestAccount3');
        insert a3;

        Contact c3 = new Contact (LastName = 'testdude3', AccountId = a3.Id); 
        insert c3;    

        POS__c p3 = new POS__c (Name  = 'Test POS');
        insert p3;

        Merchant__c m3 = new Merchant__c (Name = 'TestMerchant', merchant_id__c = 1234, Account__c = a3.Id);
        insert m3;

        Opportunity o3 = new Opportunity (Name = 'TestOppty3', Primary_Contact__c = c3.Id, Merchant__c = m3.Id, AccountId = a3.Id, StageName = 'Qualified', Probability = 10);
        insert o3;

        Location_Holder__c lh3 = new Location_Holder__c ( Opportunity__c = o3.Id, Point_of_Sale__c = p3.Id);   
        insert lh3;

        o3.Probability = 100;
        update o3;

        Location__c l3 = new Location__c ();

        String locName = lh3.Name;
        o3 = [ SELECT Merchant__c FROM Opportunity WHERE Name = 'TestOppty3'];
        l3 = [ SELECT Merchant__c FROM Location__c WHERE Name = :locName ];    

        { System.assertEquals(l3.Merchant__c, o3.Merchant__c); }

    }
}    

The trigger I'm looking to cover takes an Opportunity with custom object "Location_Holder__c" related via lookup, and creates custom object Location__c when the Opportunity is Won, porting all the field values from Location_Holder__c to the new Location__c record. What I am testing for here is to make sure that Merchant__r of the new Location__c record is the same Merchant__r on the Opportunity.

Help?

FWIW: the name of the location holder is the only field guaranteed to be unique that ports to the location, as opportunities can have multiple location holders that each spin off to their own location.

Best Answer

If your location header name is auto-number or somehow generated automatically in your triggers, you won't have the value in your test class by simply referencing lh3.Name unless you have explicitly specified it in your lh3 record before you insert it.

In this case your record name will be null and you need to re-query it:

lh3 = [SELECT Name FROM Location_Holder__c WHERE Id = :lh3.Id][0];

before you assign it to the string variable:

String locName = lh3.Name;

Related Topic