0

Here is my class for trigger that populates the custom fields on Opportunity when the custom object Property is created and unit test for it which shows the following message:

Trigger.copyPropEscrowAddressOnExchange: line 7, column 1: [] 17:58:38.2 (620530709)|USER_DEBUG|[35]|DEBUG|DmlSystem.DmlException: Insert failed. First exception on row 0; first error: CANNOT_INSERT_UPDATE_ACTIVATE_ENTITY, copyPropEscrowAddressOnExchange: execution of AfterInsert

caused by: System.NullPointerException: Attempt to de-reference a null object

Please help me to resolve the issue. I've researched the same issues on the other forums and haven't gotten a clear answer.

public with sharing class PropertyEscrowContactOnExchange {
public static void copyPropertyEscrowAddressOnExchange(List<Property__c> propList) {

    List<Id> oppIds = new List<Id>();
    Set<Id> accIds = new Set<Id>();

    for (Property__c prop : propList) {
        if (prop.Escrow_Company__c != null) {
            accIds.add(prop.Escrow_Company__c);
            oppIds.add(prop.Opportunity__c);
        }

        Map<Id, Opportunity> opportunities = new Map<Id, Opportunity>([
                SELECT Id, Name, Escrow_Company__c, Escrow_Address__c, Escrow_City__c, Escrow_State__c, Escrow_Zip_Code__c
                FROM Opportunity
                WHERE Id IN :oppIds
        ]);

        List<Opportunity> oppsToUpdate = new List<Opportunity>();

        for (Property__c p : propList) {
            Opportunity o = opportunities.get(p.Opportunity__c);
                o.Escrow_Company__c = p.Escrow_Company__c;
                o.Escrow_Address__c = p.Escrow_Address__c;
                o.Escrow_City__c = p.Escrow_City__c;
                o.Escrow_State__c = p.Escrow_State__c;
                o.Escrow_Zip_Code__c = p.Escrow_Zip_Code__c;
            oppsToUpdate.add(o);
        }
        update oppsToUpdate;
    }

 @IsTest
private class PropertyEscrowAddressTest {

    @IsTest
    static void testPropertyEscrowAddressCopiedOnExchange() {
        Account acc = new Account();
        acc.Name = acc.IsEscrow__c;
        acc.Name = 'ABM';
        insert acc;

        Opportunity opps = new Opportunity();
        opps.Name = 'testOppABC';
        opps.AccountId = acc.Id;
        opps.CloseDate = System.today();
        opps.StageName = 'Exchange Completed';
        insert opps;

        Property__c prop = new Property__c();
        prop.Name = '123 Str';
        prop.Escrow_Company__c = acc.IsEscrow__c;
        prop.Opportunity__c = opps.Id;
        prop.Escrow_Address__c = '456 Sun Str';
        prop.Escrow_City__c = 'Seattle';
        prop.Escrow_State__c = 'Washington';
        prop.Escrow_Zip_Code__c = '98765';

        Test.startTest();
        try{
            insert prop;
        }catch (DmlException e){
            System.debug('Dml' + e);
        }

        try{
            update opps;
        }catch (DmlException e){
            System.debug('Dml' + e);
        }
        Test.stopTest();

        System.assertEquals(opps.Escrow_Company__c, prop.Escrow_Company__c);

    }
3
  • The error message you've included seems to mention line 7, but in a trigger that you haven't included. Is that the full text of the error message? Are there any other lines indicated in the stack trace? – Derek F May 25 '20 at 1:18
  • You should remove the exception handlers from your unit test. Exceptions thrown in unit tests should help you locate the problem. – David Reed May 25 '20 at 1:22
  • As an aside, those try/catch statements in your test class are counterproductive. Swallowing exceptions like that (using system.debug() and then trying to continue on) is bad practice and can lead to all manner of hard to debug errors. If you get an exception in a test method, that's something that you want to cause the test to fail (except in very specific circumstances). Exceptions are usually pretty good at telling you where the issue is too. – Derek F May 25 '20 at 1:22
1

There are at least two serious bugs in this code.

    for (Property__c prop : propList) {
        if (prop.Escrow_Company__c != null) {
            accIds.add(prop.Escrow_Company__c);
            oppIds.add(prop.Opportunity__c);
        }

        Map<Id, Opportunity> opportunities = new Map<Id, Opportunity>([
                SELECT Id, Name, Escrow_Company__c, Escrow_Address__c, Escrow_City__c, Escrow_State__c, Escrow_Zip_Code__c
                FROM Opportunity
                WHERE Id IN :oppIds
        ]);

The for loop should be closed before the query. Everything after the if statement is intended to take place outside the query for bulkification purposes.

        for (Property__c p : propList) {
            Opportunity o = opportunities.get(p.Opportunity__c);
                o.Escrow_Company__c = p.Escrow_Company__c;
                o.Escrow_Address__c = p.Escrow_Address__c;
                o.Escrow_City__c = p.Escrow_City__c;
                o.Escrow_State__c = p.Escrow_State__c;
                o.Escrow_Zip_Code__c = p.Escrow_Zip_Code__c;
            oppsToUpdate.add(o);
        }

o is null, presumably because p.Opportunity__c is null. You need to check for nulls here, not above where you check prop.Escrow_Company__c for nullity (it doesn't particularly matter if the Id is null there, because a query for Id = null will return no values).

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.