2

I have a Trigger that is referencing a class. It works in Dev, but now I am trying to create the test class in order to push it to production. I am trying to test that a new user is created. I keep getting the same error System.QueryException: List has no rows for assignment to SObject. The error seems to point to the class on line 9 where the Account is added. The goal of the code is when a new user is inserted, then a contact for that new user is created as well. Does someone have any ideas why this is happening? I've used the Query Editor to make sure that the record does exist, and it does, so I'm stumped. Thanks in advance for the help.

Trigger

    trigger UserInsertContactInsert1 on User (after insert, after update) {

    if(Trigger.isAfter && Trigger.isInsert){
        Set<ID> usrIds = new Set<ID>();

        for(User u : Trigger.new){
            usrIds.add(u.id);
        }

        UserContactSyncClass1.syncContact(usrIds);  
    }

    if(Trigger.isAfter && Trigger.isUpdate){ 
        Set<ID> idSet = new Set<ID>();
        Set<ID> idSet2 = new Set<ID>();

        for(User u : trigger.new){
            for(User r : trigger.old){
                if(u.ID == r.ID && u.isActive==false && r.isActive==true){
                    idSet.add(u.ID);
                }

                if (u.ID == r.ID && u.isActive==true && r.isActive==false) {
                    idSet2.add(u.ID);
                } 
            }
        }

        UserContactSyncClass1.InactiveContact(idSet);
        UserContactSyncClass1.ActivateContact(idSet2);
    }
}

Class

public class UserContactSyncClass1 {

    @future
    public static void syncContact(Set<Id> userSet){
        List<Contact> cList = new List<Contact>();
        List<User> userList = [Select ID, FirstName, LastName, Email, Phone, True_Market_Unit__c, True_Market_Name__c FROM User WHERE ID IN :userSet];
        List<String> mList = new List<String>();
        List<String> mktList = new List<String>();
        **Account acc = [SELECT Id, Name FROM Account WHERE Name = 'Company Users' Limit 1];**

        // Loop through Users, to get List of True Market Number
        for(User usr : userList){
            mList.add(usr.True_Market_Unit__c);        
        }

        // Use the True Market Number and Match to the True Market Number in Markets
        for(Market__c mkt : [SELECT Name, Unit_Number__c FROM Market__c WHERE Unit_Number__c IN :mList]){
            mktList.add(mkt.Name);  
        }

        for(User usr : userList){
            for(String mk : mktList){
                usr.True_Market_Name__c = mk;
            }
            System.debug(usr.True_Market_Name__c);
        }

        for(User u : userList){
            cList.add(new Contact(FirstName=u.FirstName, LastName=u.LastName, User_True_Market_Name__c=u.True_Market_Name__c, Email=u.Email, Phone=u.Phone, OwnerID=u.ID, Related_User__c=u.Id, AccountId = acc.Id));
        }

        upsert cList;
    }

Test Class Method with the Error

public static testMethod void validateNewUser(){

        Profile p = [SELECT id FROM Profile WHERE Name='System Administrator'];

        User u = new User(
            FirstName = 'test', 
            LastName= 'last_test', 
            Email='[email protected]', 
            Phone='111-111-1111', 
            True_Market_Unit__c='1111', 
            alias = 'test', 
            EmailEncodingKey='UTF-8',
            ProfileId = p.Id,
            LanguageLocaleKey='en_US',
            LocaleSidKey='en_US', 
            TimeZoneSidKey='America/Los_Angeles',
            UserName = '[email protected]' 
        );

        System.runAs(u){
            System.assertEquals('111-111-1111', u.Phone);
        }

    }

Updated Solution

Turns out even though my User never referenced the account, I still needed to insert it into my test class, with the Name='Company Users' from my SOQL query. Thanks everyone for all the help.

2 Answers 2

2

Test classes do not automatically have access to Org data. Usually you have to create it as part of the test class. If you absolutely must use Org data then you can use the @isTest(SeeAllData=true) tag on your test class.

3
  • But my new user that I am inserting doesn't even reference the account at all. That's where I'm confused. It's only until later when the new Contact that I insert, when the account is referenced.
    – Stephen
    May 18, 2015 at 14:00
  • 3
    @Stephen The test class you posted doesn't even appear to insert a User - have you posted the right version? Assuming a User is inserted, your test method should itself insert an Account called "Company Users", because by default tests don't see existing org data. This isolation ensures tests will work across different orgs that contain different data.
    – Keith C
    May 18, 2015 at 14:05
  • 1
    @Stephen The "System.QueryException: List has no rows for assignment to SObject" error you are getting happens when you try to assign the results of a SOQL query to a single sObject. In your case a single Account. The User here is irrelevent, any time the "syncContact" method is called your SOQL query will run and try and return an Account record. In your test class, if you don't add the Account yourself (or use the tag) then when your test runs, Salesforce will consider that Account to not exist, and won't return anything.
    – dBeltowski
    May 18, 2015 at 14:06
0

It means you're running a SOQL query that for some reason is yielding zero results. I've also run into this during code deploys. If you add a safety to your code to safely handle zero results, you should be able to avoid the problem.

For example:

sObject[] place = [SELECT id, Name FROM sObject WHERE ... ];
integer last = place.size()-1;
if (last > 0) { 
    place[last].name  = 'hello';
}

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .