2

I'm very new to APEX and I'm trying to implement a feature where new contacts added contain a field called Company__c. From this field, a lookup is done to find the Account by the same name, and then associates the two.

My code is as follows:

trigger associateWithAccount on Contact (before insert) {
    if(Trigger.isBefore){
        if(Trigger.isInsert){
                Map<String, String> extMap = new Map<String, String>();
                Set<String> extIdSet = new Set<String>();
                for(Contact c : Trigger.new){
                    extIdSet.add(c.Company__c);
                }
            for(Account a : [select Id, Name from Account where Name IN :extIdSet]){
                extMap.put(a.Id, a.Name);
            }
            for(Contact c : Trigger.new){
                c.AccountID = extMap.get(c.Company__c);
            }
        }
    }
}

I have no idea if that works, I just know it doesn't give me any errors. However, I have no idea how to write the test class to attain the necessary code coverage, nor how to link the trigger and the test class. Any help?

This is my test code so far, but I keep getting an error about the Account__r (which I've never used before):

@isTest
private class TestAssociateWithAccount {
    static testMethod void myUnitTest() {
        Account testAccount = new Account(AccountID='98765', Account='test123');
        insert testAccount; 
        Test.startTest();
        Contact testContact = new Contact(Company__c='test123');
        insert testContact;
        Test.stopTest();
        Contact result = [select AccountID, Account__r.Name, Account__r.Account from Contact where Company__c = 'test123' limit 1];
        system.assertEquals(testAccount.AccountID, result.Contact__c);
    }
}

Thanks!

Edit: Current Trigger Code:

trigger associateWithAccount on Contact (before insert) {
    Map<String, String> extMap = new Map<String, String>();

    for(Contact c : Trigger.new){
        extMap.put(c.Company__c,null);
    }

    for(Account a : [select Id, Name from Account where Name IN :extMap.keySet()]){
        extMap.put(a.Name,a.ID);
    }
    for(Contact c : Trigger.new){
       ID tmp = extMap.get(c.Company__c); 
       if(tmp != null)
          c.AccountID = tmp;
    }
}

Current Test Class Code:

@isTest
private class TestAssociateWithAccount {
    static testMethod void myUnitTest() {
        Account testAccount = new Account(ID='5003000000D8cuI', Name='test123');
        insert testAccount; 
        Test.startTest();
        Contact testContact = new Contact(Company__c='test123');
        insert testContact;
        Test.stopTest();
         Contact result = [select AccountID, Account.Name from Contact where Company__c = 'test123' limit 1];
        system.assertEquals(testAccount.ID, result.AccountID);
    }
}
2
  • Remove the ID='5003000000D8cuI', From the Account you are creating. The ID will be populated when it is inserted
    – Eric
    Sep 24, 2015 at 21:26
  • 1
    Great Job. You passed this test. there is a lot more to do around it like covering negative cases, potential errors, etc. The test as you have it now only covers when an Account with that name exists..Now you need to cover the case if the account does not exist by name. Another for if the Contact__C is null If you do not do the other tests then it is a false sense of security. Write methods to cover every possible situation and properly assert results. Want to look at a cool package for a test factory check out - appexchange.salesforce.com/…
    – Eric
    Sep 24, 2015 at 21:31

1 Answer 1

2

Not a bad start for your first test class.

believe it or not you seem to understand what A LOT of people do not.

Now to the problem....

Standard fields do NOT have __c or __r appended to them

so the query needs to be:

Contact result = [select AccountID, Account.Name from Contact where Company__c = 'test123' limit 1];
system.assertEquals(testAccount.ID, result.AccountID);

Thinking through this logically:

You are querying for the contact and want to validate the Account related to it is the same as the testaccount...

So you need to grab the same fields that you are setting in your trigger, namely the AccountID field.

Now on to your trigger:

  1. You do not need the first two IF statements. Since the scope of the trigger is only Before Insert it will only fire for that condition. You only need the first two IF statements if the scope of the trigger covers multiple conditions

  2. The second part of your trigger will not work because you are assigning a Name to an accountID. If the contact__c is a lookup then you can simply copy the ID

Here are two versions

If Company__c is a lookup to account

trigger associateWithAccount on Contact (before insert) {
                for(Contact c : Trigger.new){
                    c.AccountID = c.Company__c;
                }
}

If Company__c is a String Name of an Account

trigger associateWithAccount on Contact (before insert) {
    Map<String, String> extMap = new Map<String, String>();

    for(Contact c : Trigger.new){
        extMap.put(c.Company__c,null);
    }

    for(Account a : [select Id, Name from Account where Name IN :extMap.keySet()]){
        extMap.put(a.Name,a.ID);
    }
    for(Contact c : Trigger.new){
       c.AccountID = extMap.get(c.Company__c); 
    }
}
8
  • Thanks! Looks like it was able to save, but when I run the test I keep getting System.TypeException: Invalid id value for this SObject type: I've tried using 15 and 18 digit sequences of characters but nothing seems to satisfy the tester.
    – AKor
    Sep 24, 2015 at 20:58
  • Is company__c a string or lookup field? If a lookup, what does it lookup to.
    – Eric
    Sep 24, 2015 at 20:59
  • It's a string. When the Contact is created, Company__c is populated with the company's name. From there, the idea is to look at accounts with matching names in order to do the association.
    – AKor
    Sep 24, 2015 at 21:04
  • Ok. Try the updated code. It should not have been an issue though but just in case. If it still errors then something else is going on. ADD to your existing question with the new code you are using (do not delete what is currently there, simply add the new information to keep the context going)
    – Eric
    Sep 24, 2015 at 21:08
  • It's only giving me an error upon testing the class, not when I try to save the code. I think it's the value I am storing in the test variable, in which case it wouldn't be a logic issue but just the way SF handles certain kinds of vars. This is the full error: System.TypeException: Invalid id value for this SObject type: 5003000000D8cuIAAR (I used an SF object ID that I found online)
    – AKor
    Sep 24, 2015 at 21:15

You must log in to answer this question.

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