Being new to salesforce i'm trying to make a prod deployment but it is failing because of code coverage issue. These are the apex classes that i wrote:
HttpCallOut.apxc
public with sharing class HttpCallOut {
@future(callout=true)
public static void callService(string endpoint, string method, string body) {
try {
Http http = new Http();
HttpRequest request = new HttpRequest();
request.setEndpoint('callout:API_SERVICES' + endpoint);
request.setMethod(method);
request.setHeader('content-type', 'application/json');
request.setBody(body);
HttpResponse response = http.send(request);
if (response.getStatusCode() != 200) {
System.debug('The status code returned was not expected: ' + response.getStatusCode() + ' ' + response.getStatus() + ' ' + response.getBody());
throw new CustomException('Error calling endpoint ' + endpoint + 'Status Code: ' + response.getStatusCode() + 'Status: ' + response.getStatus()+ 'Response Body: ' + response.getStatus());
}
return;
} catch (CalloutException calloutException) {
throw new CustomException('Error in HttpCallOut callService: ', calloutException);
}
}
}
CustomException.Apxc
public class CustomException extends Exception {
}
HandleUpdateOnReturnRefundCase
public with sharing class HandleUpdateOnReturnRefundCase {
private HttpCallOut httpCallOut = new HttpCallOut();
@InvocableMethod
public static void handleUpdateOnReturnRefundCase(List<Id> caseIds) {
List<Case> updatedCases = [select id, Decision__c, ZoroCaseIdentifier__c, Type, Description, ReturnOptions__c from Case where Id in :caseIds];
Case updatedCase = updatedCases.get(0);
if((updatedCase.Decision__c == 'Approved' && updatedCase.ReturnOptions__c != null) || updatedCase.Decision__c == 'Rejected') {
httpCallOut.callService(
'/salesforce-case-updated',
'POST',
genPayload(updatedCase.id, updatedCase.ZoroCaseIdentifier__c, updatedCase.Type)
);
} else {
throw new CustomException('Cannot update the case, please fill all required fields');
}
update updatedCases;
}
private static String genPayload(Id caseId, String zoroCaseIdentifier, String caseType) {
CasePayload casePayload = new CasePayload();
casePayload.caseId = caseId;
casePayload.caseType = caseType;
casePayload.zoroCaseIdentifier = zoroCaseIdentifier;
return JSON.serialize(casePayload);
}
}
CasePayload.Apxc
public class CasePayload {
public Id caseId {
get { return caseId; }
set { caseId = value; }
}
public String zoroCaseIdentifier {
get { return zoroCaseIdentifier; }
set { zoroCaseIdentifier = value; }
}
public String caseType {
get { return caseType; }
set { caseType = value; }
}
}
For above apex classes i have written test cases:
HandleUpdateOnReturnRefundCaseTest
@isTest
private class HandleUpdateOnReturnRefundCaseTest {
static testMethod void testApprovedReturnRefundCase() {
Case mockCase = new Case();
mockCase.Type = 'Request Return';
insert mockCase;
Test.startTest();
Test.setMock(HttpCalloutMock.class, new HttpCalloutSuccessTest());
mockCase.Decision__c = 'Approved';
mockCase.ReturnOptions__c = 'FOC without Returned Items';
update mockCase;
Test.stopTest();
List<Case> cases = [SELECT Id, Decision__c FROM Case WHERE Id = :mockCase.Id];
for (Case c : cases) {
system.assertEquals(c.Decision__c, mockCase.Decision__c);
}
}
static testMethod void testRejectedReturnRefundCase() {
Case mockCase = new Case();
mockCase.Type = 'Request Return';
insert mockCase;
Test.startTest();
Test.setMock(HttpCalloutMock.class, new HttpCalloutSuccessTest());
mockCase.Decision__c = 'Rejected';
update mockCase;
Test.stopTest();
List<Case> cases = [SELECT Id, Decision__c FROM Case WHERE Id = :mockCase.Id];
for (Case c : cases) {
system.assertEquals(c.Decision__c, mockCase.Decision__c);
}
}
static testMethod void testCaseApprovedWithoutReturnOptions() {
try
{
Case mockCase = new Case();
mockCase.Type = 'Request Return';
insert mockCase;
Test.startTest();
Test.setMock(HttpCalloutMock.class, new HttpCalloutSuccessTest());
mockCase.Decision__c = 'Approved';
mockCase.ReturnOptions__c = null;
update mockCase;
Test.stopTest();
} catch (Exception e) {
System.assert(e.getMessage().contains('Please select Return Options before saving'), 'message=' + e.getMessage());
}
}
static testMethod void testCaseUpdatedWithHttpError() {
try
{
Case mockCase = new Case();
mockCase.Type = 'Request Return';
insert mockCase;
Test.startTest();
Test.setMock(HttpCalloutMock.class, new HttpCalloutErrorTest());
mockCase.Decision__c = 'Approved';
mockCase.ReturnOptions__c = 'FOC without Returned Items';
update mockCase;
Test.stopTest();
} catch (Exception e) {
System.assert(e.getMessage().contains('Error calling endpoint /salesforce-case-updated'), 'message=' + e.getMessage());
}
}
}
HttpCalloutSuccessTest
global class HttpCalloutSuccessTest implements HttpCalloutMock{
global HttpResponse respond(HTTPRequest req){
HttpResponse res = new HttpResponse();
res.setHeader('Content-Type', 'application/json');
res.setBody('{"status":"success"}');
res.setStatusCode(200);
return res;
}
}
HttpCalloutErrorTest
@isTest
global class HttpCalloutErrorTest implements HttpCalloutMock{
global HttpResponse respond(HTTPRequest req){
HttpResponse res = new HttpResponse();
res.setStatusCode(500);
return res;
}
}
When i run the test in sandbox by clicking "Run ALL Test" - i see that cove coverage is 92%. SO i made outbound set and tried to deploy to prod.
But in prod when i validated inbound change set it complained about code code coverage issue.
Not sure what i'm doing wrong? If test cases are missing then for which part of the code?
So tests passed, no exceptions, "just" code coverage problem? You included the tests in the changeset?
This looks like it's supposed to be called from a Flow/ProcessBuilder (InvocableMethod
). Did you include that flow in package? Is it active? Or Case trigger (if it's called from trigger)
Or make the unit test call HandleUpdateOnReturnRefundCase.handleUpdateOnReturnRefundCase()
directly, without "firing mechanism". It's an unit test, not a whole system integration. Test blocks independently and composition separately, will help you nail any errors.
If you still can't figure it out - refresh new sandbox, deploy to it (without unit test run) and continue working there, examine debug logs etc.