apex-enterprise-patterns / fflib-apex-common

Common Apex Library supporting Apex Enterprise Patterns and much more!
BSD 3-Clause "New" or "Revised" License
903 stars 514 forks source link

fflib_Application.DomainFactory.newInstance line 288 NULL Pointer Exception #376

Closed AllanOricil closed 2 years ago

AllanOricil commented 2 years ago

For some weird reason Im getting this null pointer exception in this line. Im using an old version of fflib but I can't tell you which one it is. I just know it is a release before the new Domain/Trigger handler strategy.

https://github.com/apex-enterprise-patterns/fflib-apex-common/blob/ecaeb12b5f0c39426f283d7cb08d6c71e87a98f7/sfdx-source/apex-common/main/classes/fflib_Application.cls#L320

image

This is where the exception started in my code

image

My Test

@IsTest
    static void  itShouldComputeBody() {
        DSP_DocumentSigningRequestsServiceImpl service = new DSP_DocumentSigningRequestsServiceImpl();
        List<Id> parentIds = new List<Id>{
            fflib_IDGenerator.generate(Schema.Opportunity.SObjectType),
            fflib_IDGenerator.generate(Schema.Opportunity.SObjectType),
            fflib_IDGenerator.generate(Schema.Opportunity.SObjectType)
        };

        DocumentSigningRequest__c documentSignignRequest = new DocumentSigningRequest__c(
                Status__c = 'New', 
                ParentId__c = parentIds[0], 
                Id = fflib_IDGenerator.generate(Schema.DocumentSigningRequest__c.SObjectType)
        );

        List<DocumentSigningRequestSigner__c> documentSigningRequestSigners = new List<DocumentSigningRequestSigner__c>
        {
            new DocumentSigningRequestSigner__c(
                Contact__r = new Contact (
                                Id = fflib_IDGenerator.generate(Schema.Contact.SObjectType), 
                                FirstName = 'Test',
                                LastName = 'Test',
                                Email = 'test@test.com',
                                Phone = '0000000000'
                            ),
                DocumentSigningRequest__r = documentSignignRequest
            )
        };

        List<DocumentSigningRequest__c> documentSigningRequests = new List<DocumentSigningRequest__c>
        {
            documentSignignRequest
        };

        Map<Id, DocumentSigningRequest__c> documentSigningRequestsMappedById = new Map<Id, DocumentSigningRequest__c>(documentSigningRequests);

        List<ContentDocumentLink> contentDocumentLinks = new List<ContentDocumentLink>{
            new ContentDocumentLink(
                LinkedEntityId = parentIds[0], 
                Id = fflib_IDGenerator.generate(Schema.ContentDocumentLink.SObjectType)
            )
        };

        Map<Id, List<ContentDocumentLink>> contentDocumentLinksGroupedByLinkedEntityId = new Map<Id, List<ContentDocumentLink>>();
        contentDocumentLinksGroupedByLinkedEntityId.put(parentIds[0], contentDocumentLinks);

        Set<Id> documentSigningRequestIds = new Map<Id, SObject>(documentSigningRequests).keySet();

        Map<Id, String> bodyMappedByDocumentSigningRequestId = new Map<Id, String>();
        bodyMappedByDocumentSigningRequestId.put(
            documentSigningRequests[0].Id,
            service.createSigning(
                documentSigningRequests[0],
                documentSigningRequestSigners,
                contentDocumentLinksGroupedByLinkedEntityId
            ).serialize()
        );

        fflib_ApexMocks mocks = new fflib_ApexMocks();
        fflib_ISObjectUnitOfWork unitOfWorkMock = new fflib_SObjectMocks.SObjectUnitOfWork(mocks);
        DSP_IDocumentSigningRequests documentSigningRequestsMock = (DSP_IDocumentSigningRequests) mocks.mock(DSP_DocumentSigningRequests.class);
        DSP_IContentDocumentLinks contentDocumentLinksMock = (DSP_IContentDocumentLinks) mocks.mock(DSP_ContentDocumentLinks.class);
        DSP_IDocumentSigningRequestsSelector documentSigningRequestsSelectorMock = (DSP_IDocumentSigningRequestsSelector) mocks.mock(DSP_DocumentSigningRequestsSelector.class);
        DSP_IContentDocumentLinksSelector contentDocumentLinkSelectorMock = (DSP_IContentDocumentLinksSelector) mocks.mock(DSP_ContentDocumentLinksSelector.class);

        mocks.startStubbing();
        mocks.when(documentSigningRequestsMock.sObjectType()).thenReturn(DocumentSigningRequest__c.SObjectType);
        mocks.when(documentSigningRequestsMock.getDocumentSigningRequests()).thenReturn(documentSigningRequests);
        mocks.when(documentSigningRequestsMock.getParentIds()).thenReturn(new Set<Id>(parentIds));
        mocks.when(documentSigningRequestsMock.getRecordsMap()).thenReturn(documentSigningRequestsMappedById);
        mocks.when(documentSigningRequestsSelectorMock.sObjectType()).thenReturn(DocumentSigningRequest__c.SObjectType);
        mocks.when(documentSigningRequestsSelectorMock.selectAllWithSignersById(documentSigningRequestIds)).thenReturn(documentSigningRequests);

        mocks.when(contentDocumentLinksMock.sObjectType()).thenReturn(ContentDocumentLink.SObjectType);
        mocks.when(contentDocumentLinksMock.getContentDocumentLinks()).thenReturn(contentDocumentLinks);
        mocks.when(contentDocumentLinksMock.getGroupedByLinkedEntityId()).thenReturn(contentDocumentLinksGroupedByLinkedEntityId);
        mocks.when(contentDocumentLinkSelectorMock.sObjectType()).thenReturn(ContentDocumentLink.SObjectType);
        mocks.when(contentDocumentLinkSelectorMock.selectAllInLinkedEntityIds(new Set<Id>{parentIds[0]})).thenReturn(contentDocumentLinks);
        mocks.stopStubbing();

        DSP_Application.UnitOfWork.setMock(unitOfWorkMock);
        DSP_Application.Domain.setMock(documentSigningRequestsMock);
        DSP_Application.Domain.setMock(contentDocumentLinksMock);
        DSP_Application.Selector.setMock(documentSigningRequestsSelectorMock);
        DSP_Application.Selector.setMock(contentDocumentLinkSelectorMock);

        Test.startTest();
        service.computeBody(documentSigningRequests);
        Test.stopTest();

        ((DSP_IDocumentSigningRequests) mocks.verify(documentSigningRequestsMock)).setBody(bodyMappedByDocumentSigningRequestId);
        ((fflib_ISObjectUnitOfWork) mocks.verify(unitOfWorkMock)).registerDirty(documentSigningRequests);
        ((fflib_ISObjectUnitOfWork) mocks.verify(unitOfWorkMock)).commitWork();
    }

The service Method Im testing

public void computeBody(List<DocumentSigningRequest__c> records) {
        DSP_IDocumentSigningRequests documentSigningRequests = (DSP_IDocumentSigningRequests) DSP_Application.Domain.newInstance(
            records
        );
        Set<Id> parentIds = documentSigningRequests.getParentIds();
        List<ContentDocumentLink> parentContentDocumentLinks = DSP_ContentDocumentLinksSelector.newInstance()
            .selectAllInLinkedEntityIds(parentIds);
        DSP_IContentDocumentLinks contentDocumentLinks = (DSP_IContentDocumentLinks) DSP_Application.Domain.newInstance(
            parentContentDocumentLinks
        );
        Map<Id, List<ContentDocumentLink>> contentDocumentLinksGroupedByLinkedEntityId = contentDocumentLinks.getGroupedByLinkedEntityId();
        Map<Id, DocumentSigningRequest__c> documentSigningRequestsMappedById = documentSigningRequests.getRecordsMap();
        DSP_IDocumentSigningRequests storedDocumentSigningRequests = (DSP_IDocumentSigningRequests) DSP_Application.Domain.newInstance(
            DSP_DocumentSigningRequestsSelector.newInstance()
                .selectAllWithSignersById(documentSigningRequestsMappedById.keySet())
        );

        Map<Id, DocumentSigningRequest__c> storedDocumentSigningRequestsMap = storedDocumentSigningRequests.getRecordsMap();

        Map<Id, String> bodyMappedByDocumentSigningRequestId = new Map<Id, String>();
        for (DocumentSigningRequest__c documentSigningRequest : documentSigningRequests.getDocumentSigningRequests()) {
            bodyMappedByDocumentSigningRequestId.put(
                documentSigningRequest.Id,
                createSigning(
                        documentSigningRequest,
                        storedDocumentSigningRequestsMap.get(documentSigningRequest.Id)
                            .DocumentSigningRequestSigners__r,
                        contentDocumentLinksGroupedByLinkedEntityId
                    )
                    .serialize()
            );
        }
        documentSigningRequests.setBody(bodyMappedByDocumentSigningRequestId);
    }
AllanOricil commented 2 years ago

@wimvelzeboer @ImJohnMDaniel @afawcett could you help me to understand the problem?

AllanOricil commented 2 years ago

I fixed it. I had to mock getRecords() in both domain mocks.

...
mocks.when(documentSigningRequestsMock.getRecords()).thenReturn(documentSigningRequests);
...
mocks.when(contentDocumentLinksMock.getRecords()).thenReturn(contentDocumentLinks);