在 Salesforce 产品中部署变更集时出现问题 - 代码覆盖问题

问题描述

我是 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,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;
  }
}

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

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

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

enter image description here

解决方法

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

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

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

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