1

We have written a trigger that creates a custom object Opportunity Labor upon the insertion of an Opportunity. It works quite well in all aspects in the Sandbox, though fails during Apex testing due to a null value being returned for the Opportunity.Account.Name in the query, which causes the insertion of the Opportunity Labor object to fail.

Note: The Opportunity Labor object has no relationship to the Opportunity to allow it to be exposed to Force.com-Application profiles. All field values are passed through triggers.

I'm sure there's something basic that I'm missing. Thank you for your assistance.

Trigger:

trigger CreateOpportunityLabor on Opportunity (after insert) {
List<Opportunity> oppList = [SELECT Opportunity_ID__c, Name, Owner.Name, Account.Name 
                            FROM Opportunity
                            WHERE Id IN: Trigger.new];

for(Opportunity opp:oppList) {
    Opportunity_Labor__c oLab = new Opportunity_Labor__c();
    oLab.Name = opp.Opportunity_ID__c.replace('OPP','OPL');
    opp.Opportunity_Labor_ID__c = oLab.name;
    opp.Opportunity_Labor_Cost__c = 0.00;
    opp.Opportunity_Labor_Expense__c = 0.00;
    oLab.Opportunity_Owner__c = opp.Owner.Name;
    oLab.Opportunity_Account__c = opp.Account.Name;
    oLab.Opportunity_Name__c = opp.Name;
    oLab.Opportunity_ID__c = opp.Opportunity_ID__c;

    try {
        update opp;
        insert oLab;            
    } catch (DMLException error) {
        system.debug('Error: ' + error.getMessage());
    }
}

Test Class:

public class Test_CreateOpportunityLaborObject {

    @isTest static void testOpportunityLaborObjectCreate() {

        //Insert User
        User user = new User(FirstName = 'Techie', LastName = 'McTester', Email = 'tmctester@someplace.com', 
                             Username = 'tmctester@someplace.com', ProfileId = '00e70000000x3Hm', LocaleSidKey = 'en_US', 
                             LanguageLocaleKey = 'en_US', EmailEncodingKey = 'ISO-8859-1', 
                             TimeZoneSidKey = 'America/Chicago', Alias = 'tmctest');
        insert user;

        //Insert Account
        Account account = new Account(Name = 'Professional Testers', Industry = 'Automotive', Company_Size__c = '1-99 Employees', 
                                      BillingStreet = '12345 Somewhere St.', BillingCity = 'Somecity', BillingState = 'Somestate', 
                                      BillingPostalCode = '12345-6789', BillingCountry = 'USA');
        insert account;

        //Insert Contact
        Contact contact = new Contact(FirstName = 'John', LastName = 'Doe', Phone = '(123)456-7890',
                                     Email = 'jdoe@someplace.com', Title = 'Chief Telecom Specialist', Job_Role__c = 'Operations',
                                     Contact_Department__c = 'Sales', Account = account);
        insert contact;

        //Insert Opportunity        
        Opportunity opportunity = new Opportunity(Name = 'Implementation Opportunity', CloseDate = Date.valueOf('2014-12-31'), 
                                                 StageName = '2. Appointment', Sales_Rep_1__c = userID, LeadSource = 'None', 
                                                 Account = account);
        insert opportunity;

        //Verify Insertion of Oppportunity Labor Object by Trigger
        List<Opportunity_Labor__c> oplList = [SELECT Id FROM Opportunity_Labor__c];
        System.assertEquals(1, oplList.size(), 'Only one Opportunity Object should have been created!');
    }
}

Log snippet 1 of 2: (oLab field value assignments)

VARIABLE_ASSIGNMENT|[12]|this.Opportunity_Owner__c|"Test Owner"|0x2e86841d VARIABLE_ASSIGNMENT|[13]|this.Opportunity_Account__c|null|0x2e86841d VARIABLE_ASSIGNMENT|[14]|this.Opportunity_Name__c|"Implementation Oppor (6 more) ..."|0x2e86841d

VARIABLE_ASSIGNMENT|[15]|this.Opportunity_ID__c|"OPP022565"|0x2e86841d

Log snippet 2 of 2: (oLab insertion failure)

EXCEPTION_THROWN|[19]|System.DmlException: Insert failed. First exception on row 0; first error: REQUIRED_FIELD_MISSING, Required fields are missing: [Opportunity_Account__c]: [Opportunity_Account__c]

VARIABLE_ASSIGNMENT|[20]|error|"common.apex.runtime.impl.DmlExecutionException: Insert failed. First exception on row 0; first error: REQUIRED_FIELD_MISSING, Required fields are missing: [Opportunity_Account__c]: [Opportunity_Account__c]"|0x480744e5

USER_DEBUG|[21]|DEBUG|Error: Insert failed. First exception on row 0; first error: REQUIRED_FIELD_MISSING, Required fields are missing: [Opportunity_Account__c]: [Opportunity_Account__c]

  • What object is Opportunity_Account__c on? What is its data type? What line is the error happening on? – BarCotter Oct 21 '14 at 12:46
  • Thanks BarCotter. I suspect the error is occurring in the query, and the result of SELECT Account.Name FROM Opportunity stored in oppList. When executing the query manually outside of test, the results are fine. Opportunity_Account__c is a Text field that just stores the Name of the Account. Opportunity_Owner__c is identical only stores the Name of the Owner. Thanks. – Larry H Oct 21 '14 at 12:54
  • Opportunity_Account__c is on the Opportunity Labor object. – Larry H Oct 21 '14 at 14:02
3

The problem lies in your test data construction

It should be:

        //Insert Contact
        Contact contact = new Contact(FirstName = 'John', LastName = 'Doe', Phone = '(123)456-7890',
                                     Email = 'jdoe@someplace.com', Title = 'Chief Telecom Specialist', Job_Role__c = 'Operations',
                                     Contact_Department__c = 'Sales', 
                                     AccountId = account.id);  // set the ID field
        insert contact;

        //Insert Opportunity        
        Opportunity opportunity = new Opportunity(Name = 'Implementation Opportunity', CloseDate = Date.valueOf('2014-12-31'), 
                                                 StageName = '2. Appointment', Sales_Rep_1__c = userID, LeadSource = 'None', 
                                                 AccountId = account.id);   // set the ID field
        insert opportunity;

You were setting the relationshipname account in your test Contact and test Opportunity to the sobject account where what you need to do is set the value of the ID field, accountId, in each object to the account.id of the inserted Account

It is perfectly fine in the database to have Contacts without Accounts and Opportunities without Accounts (the standard UI won't let this happen however)

| improve this answer | |
  • That did the trick. Thank you very much for the education. – Larry H Oct 21 '14 at 18:07
  • sorry about the duplicate answer – cropredy Oct 21 '14 at 20:21

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.