Können wir zwei HTTP-Mock-Callouts in einer einzigen Testklassenmethode haben?

Aug 17 2020

In My Method zwei Callouts in einer einzigen Transaktion durchführen

  1. Zugriffstoken für diese API abrufen --> GetAccessToken
  2. Zahlung ausführen

Als ich die Testklasse lief, erhielt ich folgenden Fehler 08:50:00:839 FATAL_ERROR System.NullPointerException: Argument 2 cannot be null. in diesem Code request.setHeader('Authorization', accessTokenValue);

In meiner Mockup-Antwort stelle ich Only on Execute Payment, Can we mock the Access Token API in the Same method ein. Da die Mock-Class-Only- execute PaymentAntwort nicht in der Lage ist, den Zugriffstoken-Aufruf auszuführen, accessTokenValuewird sie auf NULL gesetzt.

Gibt es eine Möglichkeit, mehrere Mocks in einer einzigen Testklassenmethode zu haben? Führe mich dabei an. Danke

Methode:

 @AuraEnabled 
    public static boolean executepaymentbupayid(string payPalPayId , string payerid, Id familyrecId, string internalTransactionId){
        
        // string authorisation;
        string accessTokenValue;
        List<AggregateResult> aggr = [SELECT Service_Center__r.Client_ID__c,  Service_Center__r.Secret__c 
                                      ,Service_Center__r.PayPal_API__c
                                      FROM invoice__c WHERE   Student_Family__c=:familyrecId
                                      Group by Service_Center__r.Client_ID__c,  Service_Center__r.Secret__c, Service_Center__r.PayPal_API__c ];
        
        HttpResponse response = getPaypalAccessToken.GetAccessToken(String.valueOf(aggr[0].get('Client_ID__c')),String.valueOf(aggr[0].get('Secret__c')), String.valueOf(aggr[0].get('PayPal_API__c'))); 


        Map<String, Object> results = (Map<String, Object>) JSON.deserializeUntyped(response.getBody());
        if (response.getStatusCode() == 200) {           
            System.debug('results' + results.get('access_token'));
            System.debug('results' + results.get('token_type'));
            string tokentype = String.valueof(results.get('token_type'));
            string accesstoken = String.valueof(results.get('access_token'));        
            accessTokenValue = tokentype + ' ' + accesstoken;
        }
        
   
        
        executePayment executePaymentWrapper = new executePayment(); 
        executePaymentWrapper.payerid = payerid;
        String myJSON = JSON.serialize(executePaymentWrapper);
        String jsonReplacedString;
        jsonReplacedString = myJSON.replace('payerid', 'payer_id');
        
        
        string endpoint;       
        endpoint = System.Label.PayPal_Live_Execute_Payment + payPalPayId + '/execute';
     
        
        http http = new http();
        httpRequest request = new httpRequest();
        request.setMethod('POST');
        request.setEndpoint(endpoint);
        request.setHeader('Content-Type', 'application/json');
        request.setHeader('Authorization', accessTokenValue);
        request.setBody(jsonReplacedString);
        httpResponse res = http.send(request);      
        if (Res.getStatusCode() == 200){
            boolean updatePaymentReceived = paymentReceivedUpdate(familyrecId, internalTransactionId);            
            If(updatePaymentReceived){
                return true;
            }else{
                return false;
            }
        }else{
            return false;
        }        
    }

Testmethode

    @isTest
    public static void executepaymentbupayidTest(){
        Map <string,id> testData = TestDataFactory.CreateTestDate();  
        ID familyId = TestData.get('FamilyID');
        string payPalPayId ='PAYID-L43IDSI2C58062971907464F';
        string payerid ='SDV9S3QZQQPM4';
        string internalTransactionId = 'internalTransactionId';        
        test.startTest(); 
        Test.setMock(HttpCalloutMock.class, new ExecutepaymentbupayidMock()); 
        Boolean returnValue = Invoice.executepaymentbupayid(payPalPayId, payerid, familyId, internalTransactionId);
        test.stopTest();
    }

Scheinantwort:

@istest
public class ExecutepaymentbupayidMock implements HttpCalloutMock{
    
    public HTTPResponse respond(HTTPRequest request) {
        HttpResponse response = new HttpResponse();
        response.setHeader('Content-Type', 'application/json');
        response.setBody('{"id": "PAYID-L43IDSI2C58062971907464F","intent": "sale","state": "approved","cart": "8YT815237T955371T","payer": {"payment_method": "paypal","status": "VERIFIED","payer_info": {"email": "[email protected]","first_name": "Safari","last_name": "Individual","payer_id": "SDV9S3QZQQPM4","shipping_address": {"recipient_name": "Brian Robinson","line1": "4th Floor","line2": "Unit #34","city": "San Jose","state": "CA","postal_code": "95131","country_code": "US"},"phone": "4089285295","country_code": "US"}},"transactions": [{"amount": {"total": "95.00","currency": "USD","details": {"subtotal": "95.00","shipping": "0.00","insurance": "0.00","handling_fee": "0.00","shipping_discount": "0.00"}},"payee": {"merchant_id": "JKHMJ249QW9TU","email": "[email protected]"},"description": "Invoice Number - 0401","custom": "gE9SyW893fA2bMVDUwVosLpM1gKxqkx0%2B3MqYXpEDjM841djbcYnoN9%2BIgqgdass","invoice_number": "401","item_list": {"items": [{"name": "Invoice Number - 0401","description": "Session 2 (weeks of June 29-July 2 and July 6-9)","price": "95.00","currency": "USD","tax": "0.00","quantity": 1}],"shipping_address": {"recipient_name": "Brian Robinson","line1": "4th Floor","line2": "Unit #34","city": "San Jose","state": "CA","postal_code": "95131","country_code": "US"}},"related_resources": [{"sale": {"id": "2T59651963103743W","state": "completed","amount": {"total": "95.00","currency": "USD","details": {"subtotal": "95.00","shipping": "0.00","insurance": "0.00","handling_fee": "0.00","shipping_discount": "0.00"}},"payment_mode": "INSTANT_TRANSFER","protection_eligibility": "ELIGIBLE","protection_eligibility_type": "ITEM_NOT_RECEIVED_ELIGIBLE,UNAUTHORIZED_PAYMENT_ELIGIBLE","transaction_fee": {"value": "3.06","currency": "USD"},"parent_payment": "PAYID-L43IDSI2C58062971907464F","create_time": "2020-08-14T12:39:00Z","update_time": "2020-08-14T12:39:00Z","links": [{"href": "https://api.sandbox.paypal.com/v1/payments/sale/2T59651963103743W","rel": "self","method": "GET"},{"href": "https://api.sandbox.paypal.com/v1/payments/sale/2T59651963103743W/refund","rel": "refund","method": "POST"},{"href": "https://api.sandbox.paypal.com/v1/payments/payment/PAYID-L43IDSI2C58062971907464F","rel": "parent_payment","method": "GET"}]}}]}],"create_time": "2020-08-14T12:21:29Z","update_time": "2020-08-14T12:39:00Z","links": [{"href": "https://api.sandbox.paypal.com/v1/payments/payment/PAYID-L43IDSI2C58062971907464F","rel": "self","method": "GET"}]}');
        response.setStatusCode(201);
        return response; 
    }
}

Antworten

9 DavidReed Aug 17 2020 at 10:47

Ja, das können Sie mit einer von zwei Techniken.

HttpCalloutMockDie Methode von Ihrer respond()kann den Eingang überprüfen HttpRequestund basierend auf dem aufgerufenen Endpunkt, den übergebenen Parametern usw. eine andere Antwort erstellen. Auf diese Weise können Sie eine einzelne Klasse schreiben, die Antworten für mehrere Aufrufe zurückgibt, die nacheinander in Ihrem zu testenden Code erstellt wurden .

Alternativ können Sie die MultiStaticResourceCalloutMockKlasse verwenden. Mit dieser Klasse können Sie Antworttexte in statischen Ressourcen in Ihrer Anwendung speichern und den Mock für mehrere Endpunkte konfigurieren, indem setStaticResource()Sie ihn einmal pro Endpunkt aufrufen, auf den der Mock antworten soll. Dies kann Ihnen das Schreiben von Boilerplate-Code ersparen, wenn es Ihnen nichts ausmacht, Ihre Antworten in statischen Ressourcen zu speichern, anstatt sie im Code zu erstellen.