4

Another one of these, I know. I have been looking at similar errors for the last few hours with no luck. I tried using a "Try" "Catch" workaround with no luck, I tried using an Array, I tried making everything visible to the test class. I had no luck with anything, so hopefully someone here can help me out!

From what I understand, I'm getting the error because my list is returning no values, and that isn't allowed. How would I get around this in my particular case?

Here is my CLASS

public class UserContact {
    @future public static void createUserContact(set<ID> recordIDs){
        list<user> users = [SELECT ID, Firstname, Lastname, email, name, CommunityNickname, TimeZoneSidKey, LocaleSidKey, EmailEncodingKey, ProfileId, LanguageLocaleKey 
                            FROM user
                            WHERE ID in :recordIDs];
        for (user x: users){
            Account Accountx = [SELECT ID
                                FROM account];
            Contact userCon = new contact(
            AccountID = AccountX.id,
            FirstName = x.FirstName,
            LastName = x.LastName,
            email = x.Email);
            insert userCon;
            usercon.account.Name = 'Company Internal';
        }
    }
}`

Here is my TRIGGER

trigger NewUserCreatedTrigger on User (after insert) {
    user[] users = trigger.new;
UserContact.createUserContact(Trigger.newMap.keySet());

Here is my TEST CLASS

@isTest
private class UserContactTest {
testmethod static void userCreationTest(){
    //User u = UserContact.createUserContact(User.id); //Commented as it is not required
    User u = new User();
    u.Firstname = 'mike';
    u.LastName = 'Smith';
    u.email = '[email protected]';
    u.Alias = 'alias';
    u.CommunityNickname = 'commnick';
    u.EmailEncodingKey = 'UTF-8';
    u.Username = '[email protected]';
    u.TimeZoneSidKey = 'America/Denver';
    u.LocaleSidKey = 'en_US';
    u.EmailEncodingKey = 'UTF-8';
    u.LanguageLocaleKey = 'en_US';
    u.ProfileId = [SELECT id FROM profile where Name = 'System Administrator'].Id;
    insert u;
}

I'm still learning, going through the trailhead modules and other online tutorials, but going through these errors is helping me learn a lot, so I'm trying to work through them at the same time.

Thanks!

4
  • I think you need to wrap your future method in Test.startTest() and Test.EndTest() so test execution will wait for the future method to execute. List is probably returning no rows because the future method hasn't executed yet. Commented Mar 28, 2016 at 19:46
  • As illustrated in @Sebastian Kessel's answer, make sure you constrain the results of the SOQL query. Assigning the results of a SOQL query to a single SObject rather than a List results in a runtime failure unless there is 1 and only 1 result. You could change it to: List<Account> accounts = [SELECT Id FROM Account]; Or add a where clause or LIMIT clause...
    – frup42
    Commented Mar 28, 2016 at 20:37
  • Thank you! I started learning Apex maybe a week ago and have been working on this ever since. It is a project handed to me by my supervisor, and by going through all the problems like this, I'm learning faster than if I was only doing the trailhead. So, I would be setting this limit to avoid the 100-200 limit on queries right? Commented Mar 28, 2016 at 20:39
  • 1
    You are querying the Account table. If you get more than 1 row and attempt to assign that to your Accountx variable you will get the opposite of your original problem - System.QueryException: List has more than 1 row for assignment to SObject! So one way of guarding against this would be to use Account accountx = [SELECT Id FROM Account LIMIT 1]'
    – frup42
    Commented Mar 28, 2016 at 20:42

1 Answer 1

4

So, your problem is this line

Account Accountx = [SELECT ID FROM account];

and then

AccountID = AccountX.id,

Since test code cannot see any data, there are no accounts to assign. Make sure you create an account in your test code, like the sample below.

@isTest
private class UserContactTest {
testmethod static void userCreationTest(){
    Account a = new Account(Name = 'Company Internal');
    insert a;

    User u = new User();
    u.Firstname = 'mike';
    u.LastName = 'Smith';
    u.email = '[email protected]';
    u.Alias = 'alias';
    u.CommunityNickname = 'commnick';
    u.EmailEncodingKey = 'UTF-8';
    u.Username = '[email protected]';
    u.TimeZoneSidKey = 'America/Denver';
    u.LocaleSidKey = 'en_US';
    u.EmailEncodingKey = 'UTF-8';
    u.LanguageLocaleKey = 'en_US';
    u.ProfileId = [SELECT id FROM profile where Name = 'System Administrator'].Id;

   insert u;
}

However, that will fix your test failure but won't make your code work. In your trigger, you are making a SoQL query within a loop. That is a big no-no.

I am going to go ahead and assume that you do not want to get a "usercon" record created for each account in the system. That means a better way to query, and a way of figuring out which account you want to use.

With that, here is a possible example, assuming all users will go to the same account

public class UserContact {
    @future public static void createUserContact(set<ID> recordIDs){
        list<user> users = [SELECT ID, Firstname, Lastname, email, name, CommunityNickname, TimeZoneSidKey, LocaleSidKey, EmailEncodingKey, ProfileId, LanguageLocaleKey 
                            FROM user
                            WHERE ID in :recordIDs];

        String accountName = 'Company Internal'; //This is where you will provide your name (could be any other field)

        //In this query you want to "LIMIT 1" to avoid more than 1 record returning
        Account Accountx = [SELECT ID
                                FROM account
                               where Name = :accountName
                               LIMIT 1];

        List<contact> contactsToCreate = new List<Contact>();
        for (user x: users){
            Contact userCon = new contact(
            AccountID = AccountX.id,
            FirstName = x.FirstName,
            LastName = x.LastName,
            email = x.Email);
            contactsToCreate.add(userCon);
        }
        insert contactsToCreate;
    }
}

My example is almost trivial. Let me know your use case (i.e.: how do you determine the account to choose) and I can improve my sample code.

12
  • Thank you for the answer! I haven't had a chance to try it yet, but I will in a few minutes. The idea is that every time someone creates a user, a contact is automatically created and populated with some of the same information Commented Mar 28, 2016 at 20:12
  • You're welcome, Let me know! Commented Mar 28, 2016 at 20:12
  • Sorry, keep hitting the enter key before I want to post, edited the original post to explain my use case. I wouldn't touch accounts, except that when I tried to just tie Contacts to Users, it wouldn't let me, I believe because of the master-detail relationship between Accounts and Users. The only thing I'm trying to accomplish is to create a contact whenever a user is created, and give the contact the same information. I used Process Builder to do this, but it couldn't do the final part, setting the contact account name to "company internal". Which is vital. Commented Mar 28, 2016 at 20:17
  • I just updated my code (both the class and the test code). That should do it for you. Let me know if this works for you! Commented Mar 28, 2016 at 20:20
  • Just changed mine to match yours, and I got "expecting right curly bracket, found 'EOF'" On line 23 Maybe because I copied and pasted? Commented Mar 28, 2016 at 20:28

You must log in to answer this question.

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