1

I am currently struggling to write a unit test for a method in my domain class, and I'm finding it challenging to understand the logic, especially since I'm new to using the fflib-Apexmocks library. I am looking to test the generateEmailContractActivationToCustomerSignedBy method in the domain layer, as well as the sendEmailContractActivationToCustomerSignedBy() method in the service layer. Could someone please provide guidance on how to approach testing these methods? Any help would be greatly appreciated. Thank you in advance.

Service Layer method (sends email to contract record signatories, calling methods from selector layer and domain layer):

public void sendEmailContractActivationToCustomerSignedBy(Set<Id> contractIds, Boolean addCompanySignedByToCC) {
    fflib_ISObjectUnitOfWork uow = Application.UnitOfWork.newInstance(new List<SObjectType>{ EmailMessage.SObjectType });
    Set<String> extraFields = new Set<String>{'CustomerSigned.Name', 'CustomerSigned.Email', 'CompanySigned.Email'};
    List<Contract> contracts = new ContractsSelector().selectByIdWithExtraFields(contractIds, extraFields);
    IContracts domain = (IContracts) Application.Domain.newInstance(contracts);
    domain.generateEmailContractActivationToCustomerSignedBy(uow, addCompanySignedByToCC);
    try {
        uow.commitWork();
    } catch(Exception ex) {
        Logger.error(ex.getTypeName() + ' - ' + ex.getMessage());
        Logger.saveLog();
        throw ex;
    }
}

Domain Layer method (generates single email message and registers into the unit of work parameter):

public void generateEmailContractActivationToCustomerSignedBy(fflib_ISObjectUnitOfWork uow, Boolean addCompanySignedByToCC) {
    EmailTemplate temp = [SELECT Id FROM EmailTemplate 
                            WHERE DeveloperName = 'Contract_Activation_1709233479135' 
                            WITH SYSTEM_MODE];
    for(Contract contract : getContracts()) {
        if(String.isNotBlank(contract.CustomerSigned.Email)) {
            Messaging.SingleEmailMessage email = new Messaging.SingleEmailMessage();
            email.setToAddresses(new String[] { contract.CustomerSigned.Email });
            if(addCompanySignedByToCC && String.isNotBlank(contract.CompanySigned.Email)) { 
                email.setCcAddresses(new String[] { contract.CompanySigned.Email }); 
            }
            email.setTemplateId(temp.Id);
            email.setTargetObjectId(contract.CustomerSignedId);
            email.setWhatId(contract.Id);
            email.setSaveAsActivity(true);
            uow.registerEmail(email);
        }
    }
}

2 Answers 2

0

I have tried JSON.deserialize approach to be able to place necessary parent object fields into my fake record and seems like it is working for my domain class method:

    fflib_ApexMocks mocks = new fflib_ApexMocks();
    fflib_SObjectUnitOfWork uowMock = (fflib_SObjectUnitOfWork) mocks.mock(fflib_SObjectUnitOfWork.class);
    Application.UnitOfWork.setMock(uowMock);

    String contractJson = '{"Id":"8008d000000yQVeAAM","CompanySignedId":"0058d000007hQuhAAE","CustomerSignedId":"0038d00000sMKEfAAO",' +
    '"CustomerSigned":{"Name":"Test Customer","Email":"[email protected]"},"CompanySigned":{"Email":"[email protected]"}}';
    Contract contract = (Contract)JSON.deserialize(contractJson, Contract.class);
    
                                                        
    IContracts domain = Contracts.newInstance(new List<Contract>{ contract });
    domain.generateEmailContractActivationToCustomerSignedBy(uowMock, true);
    ((fflib_SObjectUnitOfWork) mocks.verify(uowMock, mocks.atLeastOnce())).registerEmail( (Messaging.SingleEmailMessage) fflib_Match.anyObject()); 
0

For the service method, you are instantiating the ContractsSelector directly verses using the Application.Seletor factory approach. Doing so limits your ability to setup a mock selector for your unit tests of this service method. So I would definitely suggest doing that.

I would certainly mock the UOW, the ContractsSelector, and the IContracts domain classes and then have at least one test method where you mock the behavior of the UOW to throw an exception. Doing all of that should give you good coverage for the service method.

For the Domain class, I would suggest setting up a EmailTemplatesSelector which would give you the ability to mock that query. I would also mock the UOW used for this method.

Have you seen the fflib_ApexMocksUtils class? The makeRelationship methods would allow you to mock contract records with the CustomerSigned and CompanySigned related records. The setReadOnlyFields methods would help with your earlier comment about needing use JSON.deserialize approach.

I hope this helps. Let me know if you have more questions.

You must log in to answer this question.

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