在 salesforce 产品中部署变更集的问题 - 代码覆盖问题

Issue deploying change set in salesforce prod - code coverage issue

作为 salesforce 的新手,我正在尝试进行产品部署,但由于代码覆盖问题而失败。 这些是我写的顶点类:

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; }
   }
}

上面的顶点类我写了测试用例:

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;
  }
}

当我 运行 通过单击“运行 所有测试”在沙箱中进行测试时 - 我看到 cove 覆盖率为 92%。所以我做了出站设置并尝试部署到产品。

但是在产品中,当我验证入站更改集时,它抱怨代码代码覆盖问题。

不确定我做错了什么?如果缺少测试用例,那么代码的哪一部分?

所以测试通过了,没有异常,“只是”代码覆盖问题?您在变更集中包含了测试?

这看起来应该从 Flow/ProcessBuilder (InvocableMethod) 中调用。您是否将该流程包含在包裹中?活跃吗?或者 Case 触发器(如果它是从触发器调用的)

或者直接让单元测试调用 HandleUpdateOnReturnRefundCase.handleUpdateOnReturnRefundCase(),没有“触发机制”。这是一个单元测试,而不是整个系统集成。独立测试块和单独组合,将帮助您纠正任何错误。

如果您仍然无法弄清楚 - 刷新新沙箱,部署到它(没有单元测试 运行)并继续在那里工作,检查调试日志等。