I'm new to SalesForce development. I have a basic Controller method that takes an Id for a "child" record (FundsRequest__c) and returns a Custom object that I define in the Controller class (FundTotals).
The custom object has a constructor method that I'm using to instantiate for the response for the method. For some reason, the values aren't getting set and instead a new FundTotals object is returned with null values for all of the properties. Here's my code:
FundsRequestCostController.cls: (Class under test)
public with sharing class FundsRequestCostsController {
@AuraEnabled
public static FundTotals getCosts(Id id) {
ccprm__FundsRequest__c request = [SELECT
ccprm__TotalCost__c,
ccprm__RequestedAmount__c,
ccprm__Campaign__r.NumberOfOpportunities,
ccprm__Campaign__r.NumberOfWonOpportunities
FROM
ccprm__FundsRequest__c
WHERE Id = :id];
FundTotals ft = new FundTotals(request.ccprm__Campaign__r.NumberOfOpportunities, request.ccprm__Campaign__r.NumberOfWonOpportunities, request.ccprm__TotalCost__c, request.ccprm__RequestedAmount__c);
System.debug(LoggingLevel.DEBUG, 'FundTotals: ' + ft);
return ft;
}
public class FundTotals {
public Integer NumberOfOpportunities;
public Integer NumberOfWonOpportunities;
public Decimal TotalCost;
public Decimal RequestedAmount;
public FundTotals(Integer numberOfOpportunities, Integer numberOfWonOpportunities, Decimal totalCost, Decimal requestedAmount) {
NumberOfOpportunities = numberOfOpportunities;
NumberOfWonOpportunities= numberOfWonOpportunities;
TotalCost = totalCost;
RequestedAmount = requestedAmount;
System.debug(LoggingLevel.DEBUG, 'FundTotals(constructor: ' + this);
System.debug(LoggingLevel.DEBUG, 'numberOfOpportunities: ' + numberOfOpportunities);
}
}
}
FundsRequestCostControllerTest.cls: (Unit test)
@IsTest
private class FundsRequestCostsControllerTest {
@IsTest
static void testBehavior() {
Campaign campaign = new Campaign();
campaign.Name = 'test campaign';
insert campaign;
for(Integer i=0; i (lessthan) 10; i++){
Opportunity opportunity = new Opportunity();
opportunity.Name = 'test opp' + i;
opportunity.Amount = 100 + i;
opportunity.StageName = 'Closed Won';
opportunity.CloseDate = date.today();
opportunity.Campaign = campaign;
insert opportunity;
}
ccprm__FundsRequest__c request = new ccprm__FundsRequest__c();
request.ccprm__TotalCost__c = 1000.00;
request.ccprm__RequestedAmount__c = 2000.00;
request.ccprm__Campaign__c = campaign.Id;
Account account = new Account();
account.Name = 'test account';
insert account;
request.ccprm__Account__c = account.Id;
insert request;
Test.startTest();
FundsRequestCostsController.FundTotals fundTotals = FundsRequestCostsController.getCosts(request.Id);
Test.stopTest();
System.assertEquals(10, fundTotals.NumberOfOpportunities);
System.assertEquals(6, fundTotals.NumberOfWonOpportunities);
System.assertEquals(10, fundTotals.RequestedAmount);
System.assertEquals(10, fundTotals.TotalCost);
}
}
Results:
In the Logs, I see that…
System.Debug(... 'FundsTotals: ' + ft)
returns:
|USER_DEBUG|[20]|DEBUG|FundTotals: FundTotals:[NumberOfOpportunities=null, NumberOfWonOpportunities=null, RequestedAmount=null, TotalCost=null]
Also…
System.debug(... 'numberOfOpportunities: ' + numberOfOpportunities)
returns:
DEBUG|numberOfOpportunities: 0
I'm confused by a few things:
- Why is the value of the parameter 0? (should be 10 with how I've created 10 opportunities in a for loop)?
- Why aren't the values (0) assigned to the FundTotals object (returns with null)?
Best Answer
Because Apex is case insensitive this:
is assigning the method parameter to itself.
Instead you need to assign the parameter value to the field like this:
(You could also use different names, but personally I prefer to use the same name and keep a look out for missing
this.
.)The
numberOfOpportunities
is zero because that is the automatically assigned default value for that type of field.