I've developed a trigger that converts a currency field, Amount (i.e. $1,000) into words, Currency_text__c (i.e. One Thousand).
This is achieved via Salesforce a 'FundingAwardTrigger' on the FundingAward object (part of the Grantmaking package). The trigger functions perfectly in Sandbox. When I run the tests in Sandbox, I get 100% coverage.
When I validate the Inbound Change Set in Prod, I get the following error:
Code Coverage Failure: The following triggers have 0% code coverage. Each trigger must have at least 1% code coverage. FundingAwardTrigger
Here's my test class:
@isTest
private class FundingAwardTriggerTest {
@isTest static void testTriggerOnInsert() {
// Create a test record for the insert operation
FundingAward testAwardInsert = new FundingAward(Name = 'Test Insert', Amount = 100);
// Start the test context
Test.startTest();
// Perform the insert operation
insert testAwardInsert;
// Stop the test context
Test.stopTest();
// Retrieve the inserted record and assert the result
testAwardInsert = [SELECT Currency_Text__c FROM FundingAward WHERE Id = :testAwardInsert.Id];
System.assertEquals('One Hundred', testAwardInsert.Currency_Text__c, 'Trigger did not work as expected on insert');
}
@isTest static void testTriggerOnUpdate() {
// Create and insert a record for the update operation
FundingAward testAwardUpdate = new FundingAward(Name = 'Test Update', Amount = 100);
insert testAwardUpdate;
// Start the test context
Test.startTest();
// Perform the update operation
testAwardUpdate.Amount = 200;
update testAwardUpdate;
// Stop the test context
Test.stopTest();
// Retrieve the updated record and assert the result
testAwardUpdate = [SELECT Currency_Text__c FROM FundingAward WHERE Id = :testAwardUpdate.Id];
System.assertEquals('Two Hundred', testAwardUpdate.Currency_Text__c, 'Trigger did not work as expected on update');
}
@isTest static void testBulkOperation() {
// Create multiple records for testing bulk operation
List<FundingAward> awards = new List<FundingAward>();
for (Integer i = 1; i <= 10; i++) {
awards.add(new FundingAward(Name = 'Bulk Test Award ' + i, Amount = i * 100));
}
// Start the test context
Test.startTest();
// Perform bulk insert
insert awards;
// Update the records for bulk update test
for (Integer i = 0; i < awards.size(); i++) {
awards[i].Amount += 1000;
}
// Perform bulk update
update awards;
// Stop the test context
Test.stopTest();
}
}
Why would my test class show 100% in sandbox but 0% in prod?
And for context, here is my Apex class:
public class CurrencyToWords {
public static String convert(Decimal amount) {
if (amount == null) return '';
// Convert Decimal to Integer for easier handling
Integer intAmount = amount.intValue();
// Return "Zero" immediately if amount is 0
if (intAmount == 0) {
return 'Zero';
}
// Arrays for number names
String[] units = new String[]{'Zero', 'One', 'Two', 'Three', 'Four', 'Five', 'Six', 'Seven', 'Eight', 'Nine'};
String[] teens = new String[]{'Ten', 'Eleven', 'Twelve', 'Thirteen', 'Fourteen', 'Fifteen', 'Sixteen', 'Seventeen', 'Eighteen', 'Nineteen'};
String[] tens = new String[]{'', 'Ten', 'Twenty', 'Thirty', 'Forty', 'Fifty', 'Sixty', 'Seventy', 'Eighty', 'Ninety'};
String result = '';
// Handling millions
Integer millions = intAmount / 1000000;
result += millions > 0 ? units[millions] + ' Million ' : '';
intAmount -= millions * 1000000; // Remaining amount after subtracting millions
// Handling hundreds of thousands
Integer hundredThousands = intAmount / 1000;
result += hundredThousands > 0 ? convertHundreds(hundredThousands) + ' Thousand ' : '';
intAmount -= hundredThousands * 1000; // Remaining amount after subtracting hundred thousands
// Handling the rest (hundreds, tens, and ones)
if (intAmount > 0) {
result += convertHundreds(intAmount);
}
return result.trim();
}
// Helper method to convert hundreds part
private static String convertHundreds(Integer amount) {
String[] units = new String[]{'Zero', 'One', 'Two', 'Three', 'Four', 'Five', 'Six', 'Seven', 'Eight', 'Nine'};
String[] teens = new String[]{'Ten', 'Eleven', 'Twelve', 'Thirteen', 'Fourteen', 'Fifteen', 'Sixteen', 'Seventeen', 'Eighteen', 'Nineteen'};
String[] tens = new String[]{'', 'Ten', 'Twenty', 'Thirty', 'Forty', 'Fifty', 'Sixty', 'Seventy', 'Eighty', 'Ninety'};
String result = '';
Integer hundreds = amount / 100;
result += hundreds > 0 ? units[hundreds] + ' Hundred ' : '';
Integer lastTwoDigits = amount - (hundreds * 100); // Calculating the last two digits manually
if (lastTwoDigits < 20 && lastTwoDigits > 9) {
result += teens[lastTwoDigits - 10] + ' ';
} else {
Integer tensPlace = lastTwoDigits / 10;
Integer onesPlace = lastTwoDigits - (tensPlace * 10); // Calculating ones place manually
if (tensPlace > 0) {
result += tens[tensPlace] + ' ';
}
if (onesPlace > 0) {
result += units[onesPlace] + ' ';
}
}
return result;
}
}
And the trigger:
trigger FundingAwardTrigger on FundingAward (before insert, before update) {
for (FundingAward fa : Trigger.new) {
fa.Currency_Text__c = CurrencyToWords.convert(fa.Amount);
}
}
Any tips are appreciated!